﻿//-----------------------------------------------------------------------
// <copyright file="MannersExecutor.cs" company="tuliprules.org">
//     Copyright (c) 2010 tuplelister, tuliprules.org.
// </copyright>
// <summary>This is the MannersExecutor class.</summary>
//-----------------------------------------------------------------------

////#define EVAL_COUNTS

namespace Tulip.Manners
{
    using System;
    using System.Collections.Generic;
    using Benchmarks.Manners.Model;
    using Tulip.Engine;
    using Tulip.Engine.ConflictResolution;
    using Tulip.Engine.EngineOperation;
    using Tulip.Engine.Tuples;
    using Tuple = Tulip.Engine.Tuples.Tuple;

    /// <summary>
    /// Hand-crafted Executor.  This code represents the output of the code generator.
    /// </summary>
    public class MannersExecutor : Executor
    {
#if EVAL_COUNTS
        public static Dictionary<string, int> EvalCounts = new Dictionary<string, int>();

        public static void IncrementEvalCount(string funcName)
        {
            int currentCount;

            if (funcName.Length < 40)
            {
                System.Text.StringBuilder sb = new StringBuilder("                                                  ", 0, 40 - funcName.Length, 80);
                funcName += sb.ToString();
            }
            if (!MannersExecutor.EvalCounts.TryGetValue(funcName, out currentCount))
            {
                MannersExecutor.EvalCounts.Add(funcName, 1);
            }
            else
            {
                MannersExecutor.EvalCounts[funcName] = MannersExecutor.EvalCounts[funcName] + 1;
            }

        }
#endif
        private readonly ConflictResolutionStrategy crStrategy;

        // Cache agenda lists
        private readonly IAgendaList agendaPriority0;
        private readonly IAgendaList agendaPriority1;

        // Cache 'All' Tuple Lists
        private TupleLinkedList j6TupleList;
        private TupleLinkedList j8TupleList;
        private TupleLinkedList guestTupleList;
        private TupleLinkedList contextStartTupleList;
        private TupleLinkedList contextAssignSeatTupleList;
        private TupleLinkedList contextMakePathTupleList;
        private TupleLinkedList contextCheckDoneTupleList;
        private TupleLinkedList contextPrintResultsTupleList;
        private TupleLinkedList countTupleList;
        private TupleLinkedList j1TupleList;
        private TupleLinkedList seatingTupleList;
        private TupleLinkedList seatingNoTupleList;
        private TupleLinkedList seatingYesTupleList;
        private TupleLinkedList j5TupleList;
        private TupleLinkedList lastSeatTupleList;

        // cache all MonadicFunction delegates
        MonadicFunction join1AFunc;
        MonadicFunction join1BFunc;
        private MonadicFunction join2AFunc;
        private MonadicFunction join2BFunc;
        private MonadicFunction join3AFunc;
        private MonadicFunction join3BFunc;
        private MonadicFunction join4AFunc;
        private MonadicFunction join4BFunc;
        private MonadicFunction join5AFunc;
        private MonadicFunction join5BFunc;
        private MonadicFunction join6AFunc;
        private MonadicFunction join6BFunc;
        private MonadicFunction join7AFunc;
        private MonadicFunction join7BFunc;
        private MonadicFunction join8AFunc;
        private MonadicFunction join8BFunc;
        private MonadicFunction join9AFunc;
        private MonadicFunction join9BFunc;
        private MonadicFunction join10AFunc;
        private MonadicFunction join10BFunc;
        private MonadicFunction join11AFunc;
        private MonadicFunction join11BFunc;
        private MonadicFunction join12AFunc;
        private MonadicFunction join12BFunc;
        private MonadicFunction join13AFunc;
        private MonadicFunction join13BFunc;
        private MonadicFunction not1AFunc;
        private MonadicFunction not1BFunc;
        private MonadicFunction not2AFunc;
        private MonadicFunction not2BFunc;
        private MonadicFunction not3AFunc;
        private MonadicFunction not3BFunc;
        private MonadicFunction contextStateFunc;
        private MonadicFunction seatingPathDoneFunc;
        private MonadicFunction t1AssignFirstSeatFunc;
        private MonadicFunction t2FindSeatingFunc;
        private MonadicFunction t3MakePathFunc;
        private MonadicFunction t4PathDoneFunc;
        private MonadicFunction t5AreWeDoneFunc;
        private MonadicFunction t6ContinueFunc;
        private MonadicFunction t7PrintResultsFunc;
        private MonadicFunction t8AllDoneFunc;

        private TupleIndexer<EtChosen> chosenIdNameHobbyIndexer;
        private TupleIndexer<EtPath> pathIdNameIndexer;
        private TupleIndexer<EtGuest> guestNameIndexer;
        private TupleIndexer<EtGuest> guestSexHobbyIndexer;
        private TupleIndexer<EtSeating> seatingSeat2Indexer;
        private TupleIndexer<EtLastSeat> lastSeatSeatIndexer;
        private TupleIndexer<J3> jSeq2J3SeatingName2Indexer;
        private TupleIndexer<J4> jSeq2J4GuestSexHobbyIndexer;
        private TupleIndexer<J7> jSeq3J7SeatingPidIndexer;
        private TupleIndexer<J9> jSeq4J9LastSeatingSeatIndexer;
        private TupleIndexer<J11> jSeq5J11SeatingSeat2Indexer;
        private TupleIndexer<J12> jSeq5J12SeatingIdIndexer;

        private TupleIndexer<EtCount> countIndexer;
        private TupleIndexer<EtGuest> guestIndexer;
        private TupleIndexer<EtLastSeat> lastSeatIndexer;
        private TupleIndexer<EtContext> contextStartIndexer;
        private TupleIndexer<EtContext> contextAssignSeatsIndexer;
        private TupleIndexer<EtContext> contextMakePathIndexer;
        private TupleIndexer<EtContext> contextCheckDoneIndexer;
        private TupleIndexer<EtContext> contextPrintResultsIndexer;
        private TupleIndexer<EtSeating> seatingIndexer;
        private TupleIndexer<EtSeating> seatingYesIndexer;
        private TupleIndexer<EtSeating> seatingNoIndexer;
        private TupleIndexer<J1> j1Indexer;
        private TupleIndexer<J5> j5Indexer;
        private TupleIndexer<J6> j6Indexer;
        private TupleIndexer<J8> j8Indexer;

        // Declare tuple relations
        private ITupleRelation<EtCount> trCount;
        private ITupleRelation<EtGuest> trGuest;
        private ITupleRelation<EtChosen> trChosen;
        private ITupleRelation<EtPath> trPath;
        private ITupleRelation<EtLastSeat> trLastSeat;
        private ITupleRelation<EtContext> trContextStart;
        private ITupleRelation<EtContext> trContextAssignSeats;
        private ITupleRelation<EtContext> trContextMakePath;
        private ITupleRelation<EtContext> trContextCheckDone;
        private ITupleRelation<EtContext> trContextPrintResults;
        private ITupleRelation<EtSeating> trSeating;
        private ITupleRelation<EtSeating> trSeatingYes;
        private ITupleRelation<EtSeating> trSeatingNo;
        private ITupleRelation<J1> trJ1;
        private ITupleRelation<J3> trJ3;
        private ITupleRelation<J4> trJ4;
        private ITupleRelation<J5> trJ5;
        private ITupleRelation<J6> trJ6;
        private ITupleRelation<J7> trJ7;
        private ITupleRelation<J8> trJ8;
        private ITupleRelation<J9> trJ9;
        private ITupleRelation<J11> trJ11;
        private ITupleRelation<J12> trJ12;

        private readonly Dictionary<Type, SelectionTargets> typeDictionary = new Dictionary<Type, SelectionTargets>();
        private readonly Dictionary<string, SelectionTargets> seatingPathDoneDictionary = new Dictionary<string, SelectionTargets>();
        private readonly Dictionary<string, SelectionTargets> contextStateDictionary = new Dictionary<string, SelectionTargets>();

        private Dictionary<int, TupleLinkedList> tvChosenIdNameHobby;
        private Dictionary<int, TupleLinkedList> tvPathIdName;
        private Dictionary<string, TupleLinkedList> tvGuestName;
        private Dictionary<int, TupleLinkedList> tvSeatingSeat2;
        private Dictionary<int, TupleLinkedList> tvLastSeatSeat;
        private Dictionary<string, TupleLinkedList> tvJSeq2J3SeatingName2;
        private Dictionary<int, TupleLinkedList> tvJSeq3J7SeatingPid;
        private Dictionary<int, TupleLinkedList> tvJSeq4J9LastSeatingSeat;
        private Dictionary<int, TupleLinkedList> tvJSeq5J11SeatingSeat2;
        private Dictionary<int, TupleLinkedList> tvJSeq5J12SeatingId;

        #region Constructors

        public MannersExecutor()
        {
            Initialise();

            this.crStrategy = new DepthFirstStrategy();
            //_crStrategy = new RandomStrategy();
            //_crStrategy = new BreadthFirstStrategy();
            this.agenda = this.crStrategy.NewAgenda();
            this.session.Agenda = this.agenda;

            this.agendaPriority0 = this.agenda.RegisterPriorityClass(0);
            this.agendaPriority1 = this.agenda.RegisterPriorityClass(1);
        }

        #endregion Constructors

        private void Initialise()
        {
            // Create a new session
            this.session = TupleStore.GetTupleStoreSession();
            this.engine = new Engine();

            this.join1AFunc = new MonadicFunction(this.Join1A);
            this.join1BFunc = new MonadicFunction(this.Join1B);
            this.join2AFunc = new MonadicFunction(this.Join2A);
            this.join2BFunc = new MonadicFunction(this.Join2B);
            this.join3AFunc = new MonadicFunction(this.Join3A);
            this.join3BFunc = new MonadicFunction(this.Join3B);
            this.join4AFunc = new MonadicFunction(this.Join4A);
            this.join4BFunc = new MonadicFunction(this.Join4B);
            this.join5AFunc = new MonadicFunction(this.Join5A);
            this.join5BFunc = new MonadicFunction(this.Join5B);
            this.join6AFunc = new MonadicFunction(this.Join6A);
            this.join6BFunc = new MonadicFunction(this.Join6B);
            this.join7AFunc = new MonadicFunction(this.Join7A);
            this.join7BFunc = new MonadicFunction(this.Join7B);
            this.join8AFunc = new MonadicFunction(this.Join8A);
            this.join8BFunc = new MonadicFunction(this.Join8B);
            this.join9AFunc = new MonadicFunction(this.Join9A);
            this.join9BFunc = new MonadicFunction(this.Join9B);
            this.join10AFunc = new MonadicFunction(this.Join10A);
            this.join10BFunc = new MonadicFunction(this.Join10B);
            this.join11AFunc = new MonadicFunction(this.Join11A);
            this.join11BFunc = new MonadicFunction(this.Join11B);
            this.join12AFunc = new MonadicFunction(this.Join12A);
            this.join12BFunc = new MonadicFunction(this.Join12B);
            this.join13AFunc = new MonadicFunction(this.Join13A);
            this.join13BFunc = new MonadicFunction(this.Join13B);
            this.not1AFunc = new MonadicFunction(this.Not1A);
            this.not1BFunc = new MonadicFunction(this.Not1B);
            this.not2AFunc = new MonadicFunction(this.Not2A);
            this.not2BFunc = new MonadicFunction(this.Not2B);
            this.not3AFunc = new MonadicFunction(this.Not3A);
            this.not3BFunc = new MonadicFunction(this.Not3B);
            this.contextStateFunc = new MonadicFunction(this.ContextState);
            this.seatingPathDoneFunc = new MonadicFunction(this.SeatingPathDone);
            this.t1AssignFirstSeatFunc = new MonadicFunction(this.T1AssignFirstSeat);
            this.t2FindSeatingFunc = new MonadicFunction(this.T2FindSeating);
            this.t3MakePathFunc = new MonadicFunction(this.T3MakePath);
            this.t4PathDoneFunc = new MonadicFunction(this.T4PathDone);
            this.t5AreWeDoneFunc = new MonadicFunction(this.T5AreWeDone);
            this.t6ContinueFunc = new MonadicFunction(this.T6Continue);
            this.t7PrintResultsFunc = new MonadicFunction(this.T7PrintResults);
            this.t8AllDoneFunc = new MonadicFunction(this.T8AllDone);

            // Register tuple relations.   This is equivalent to creating memories.
            this.trCount = TupleStore.RegisterTupleRelation<EtCount>(1, this.session);
            this.trGuest = TupleStore.RegisterTupleRelation<EtGuest>(2, this.session);
            this.trChosen = TupleStore.RegisterTupleRelation<EtChosen>(3, this.session);
            this.trPath = TupleStore.RegisterTupleRelation<EtPath>(4, this.session);
            this.trLastSeat = TupleStore.RegisterTupleRelation<EtLastSeat>(5, this.session);
            this.trContextStart = TupleStore.RegisterTupleRelation<EtContext>(6, this.session);
            this.trContextAssignSeats = TupleStore.RegisterTupleRelation<EtContext>(7, this.session);
            this.trContextMakePath = TupleStore.RegisterTupleRelation<EtContext>(8, this.session);
            this.trContextCheckDone = TupleStore.RegisterTupleRelation<EtContext>(9, this.session);
            this.trContextPrintResults = TupleStore.RegisterTupleRelation<EtContext>(10, this.session);
            this.trSeating = TupleStore.RegisterTupleRelation<EtSeating>(11, this.session);
            this.trSeatingYes = TupleStore.RegisterTupleRelation<EtSeating>(12, this.session);
            this.trSeatingNo = TupleStore.RegisterTupleRelation<EtSeating>(13, this.session);
            this.trJ1 = TupleStore.RegisterTupleRelation<J1>(14, this.session);
            this.trJ3 = TupleStore.RegisterTupleRelation<J3>(15, this.session);
            this.trJ4 = TupleStore.RegisterTupleRelation<J4>(16, this.session);
            this.trJ5 = TupleStore.RegisterTupleRelation<J5>(17, this.session);
            this.trJ6 = TupleStore.RegisterTupleRelation<J6>(18, this.session);
            this.trJ7 = TupleStore.RegisterTupleRelation<J7>(19, this.session);
            this.trJ8 = TupleStore.RegisterTupleRelation<J8>(20, this.session);
            this.trJ9 = TupleStore.RegisterTupleRelation<J9>(21, this.session);
            this.trJ11 = TupleStore.RegisterTupleRelation<J11>(22, this.session);
            this.trJ12 = TupleStore.RegisterTupleRelation<J12>(23, this.session);

            // Create 'All' Indexers
            this.countIndexer = new TupleIndexer<EtCount>(0);
            this.guestIndexer = new TupleIndexer<EtGuest>(0);
            this.lastSeatIndexer = new TupleIndexer<EtLastSeat>(0);
            this.contextStartIndexer = new TupleIndexer<EtContext>(0);
            this.contextAssignSeatsIndexer = new TupleIndexer<EtContext>(1);
            this.contextMakePathIndexer = new TupleIndexer<EtContext>(2);
            this.contextCheckDoneIndexer = new TupleIndexer<EtContext>(3);
            this.contextPrintResultsIndexer = new TupleIndexer<EtContext>(4);
            this.seatingIndexer = new TupleIndexer<EtSeating>(0);
            this.seatingYesIndexer = new TupleIndexer<EtSeating>(1);
            this.seatingNoIndexer = new TupleIndexer<EtSeating>(2);
            this.j1Indexer = new TupleIndexer<J1>(0);
            this.j5Indexer = new TupleIndexer<J5>(0);
            this.j6Indexer = new TupleIndexer<J6>(1);
            this.j8Indexer = new TupleIndexer<J8>(0);

            // Create other Indexers

            this.chosenIdNameHobbyIndexer = new TupleIndexer<EtChosen>(0, new TupleIndexerEvaluationRecord<EtChosen>(Evaluators.EvaluatorChosenId, TupleLinkedList.GetTupleView<Int32>)
                                                                         , new TupleIndexerEvaluationRecord<EtChosen>(Evaluators.EvaluatorChosenName, TupleLinkedList.GetTupleView<String>)
                                                                         , new TupleIndexerEvaluationRecord<EtChosen>(Evaluators.EvaluatorChosenHobby, TupleLinkedList.GetTupleView<String>));
            this.pathIdNameIndexer = new TupleIndexer<EtPath>(0, new TupleIndexerEvaluationRecord<EtPath>(Evaluators.EvaluatorPathId, TupleLinkedList.GetTupleView<Int32>)
                                                                , new TupleIndexerEvaluationRecord<EtPath>(Evaluators.EvaluatorPathName, TupleLinkedList.GetTupleView<String>));
            this.guestNameIndexer = new TupleIndexer<EtGuest>(1, new TupleIndexerEvaluationRecord<EtGuest>(Evaluators.EvaluatorGuestName, TupleLinkedList.GetTupleView<String>));
            this.guestSexHobbyIndexer = new TupleIndexer<EtGuest>(2, new TupleIndexerEvaluationRecord<EtGuest>(Evaluators.EvaluatorGuestSex, TupleLinkedList.GetTupleView<String>)
                                                                    , new TupleIndexerEvaluationRecord<EtGuest>(Evaluators.EvaluatorGuestHobby, TupleLinkedList.GetTupleView<String>));
            this.seatingSeat2Indexer = new TupleIndexer<EtSeating>(3, new TupleIndexerEvaluationRecord<EtSeating>(Evaluators.EvaluatorSeatingSeat2, TupleLinkedList.GetTupleView<Int32>));
            this.lastSeatSeatIndexer = new TupleIndexer<EtLastSeat>(1, new TupleIndexerEvaluationRecord<EtLastSeat>(Evaluators.EvaluatorLastSeatSeat, TupleLinkedList.GetTupleView<Int32>));
            this.jSeq2J3SeatingName2Indexer = new TupleIndexer<J3>(2, new TupleIndexerEvaluationRecord<J3>(Evaluators.EvaluatorJSeq2J3SeatingName2, TupleLinkedList.GetTupleView<String>));
            this.jSeq2J4GuestSexHobbyIndexer = new TupleIndexer<J4>(3, new TupleIndexerEvaluationRecord<J4>(Evaluators.EvaluatorJSeq2J4GuestSex, TupleLinkedList.GetTupleView<String>)
                                                                      , new TupleIndexerEvaluationRecord<J4>(Evaluators.EvaluatorJSeq2J4GuestHobby, TupleLinkedList.GetTupleView<String>));
            this.jSeq3J7SeatingPidIndexer = new TupleIndexer<J7>(0, new TupleIndexerEvaluationRecord<J7>(Evaluators.EvaluatorJSeq3J7SeatingPid, TupleLinkedList.GetTupleView<Int32>));
            this.jSeq4J9LastSeatingSeatIndexer = new TupleIndexer<J9>(0, new TupleIndexerEvaluationRecord<J9>(Evaluators.EvaluatorJSeq4J9LastSeatingSeat, TupleLinkedList.GetTupleView<Int32>));
            this.jSeq5J11SeatingSeat2Indexer = new TupleIndexer<J11>(0, new TupleIndexerEvaluationRecord<J11>(Evaluators.EvaluatorJSeq5J11SeatingSeat2, TupleLinkedList.GetTupleView<Int32>));
            this.jSeq5J12SeatingIdIndexer = new TupleIndexer<J12>(0, new TupleIndexerEvaluationRecord<J12>(Evaluators.EvaluatorJSeq5J12SeatingId, TupleLinkedList.GetTupleView<Int32>));

            // Register 'all' evaluators
            this.trCount.RegisterAllIndexer(this.countIndexer);
            this.trGuest.RegisterAllIndexer(this.guestIndexer);
            this.trLastSeat.RegisterAllIndexer(this.lastSeatIndexer);
            this.trContextStart.RegisterAllIndexer(this.contextStartIndexer);
            this.trContextAssignSeats.RegisterAllIndexer(this.contextAssignSeatsIndexer);
            this.trContextMakePath.RegisterAllIndexer(this.contextMakePathIndexer);
            this.trContextCheckDone.RegisterAllIndexer(this.contextCheckDoneIndexer);
            this.trContextPrintResults.RegisterAllIndexer(this.contextPrintResultsIndexer);
            this.trSeating.RegisterAllIndexer(this.seatingIndexer);
            this.trSeatingYes.RegisterAllIndexer(this.seatingYesIndexer);
            this.trSeatingNo.RegisterAllIndexer(this.seatingNoIndexer);
            this.trJ1.RegisterAllIndexer(this.j1Indexer);
            this.trJ5.RegisterAllIndexer(this.j5Indexer);
            this.trJ6.RegisterAllIndexer(this.j6Indexer);
            this.trJ8.RegisterAllIndexer(this.j8Indexer);

            // Register other evaluators
            this.trChosen.RegisterIndexer<int>(this.chosenIdNameHobbyIndexer);
            this.trPath.RegisterIndexer<int>(this.pathIdNameIndexer);
            this.trGuest.RegisterIndexer<string>(this.guestNameIndexer);
            this.trGuest.RegisterIndexer<string>(this.guestSexHobbyIndexer);
            this.trSeating.RegisterIndexer<int>(this.seatingSeat2Indexer);
            this.trLastSeat.RegisterIndexer<int>(this.lastSeatSeatIndexer);
            this.trJ3.RegisterIndexer<string>(this.jSeq2J3SeatingName2Indexer);
            this.trJ4.RegisterIndexer<string>(this.jSeq2J4GuestSexHobbyIndexer);
            this.trJ7.RegisterIndexer<int>(this.jSeq3J7SeatingPidIndexer);
            this.trJ9.RegisterIndexer<int>(this.jSeq4J9LastSeatingSeatIndexer);
            this.trJ11.RegisterIndexer<int>(this.jSeq5J11SeatingSeat2Indexer);
            this.trJ12.RegisterIndexer<int>(this.jSeq5J12SeatingIdIndexer);

            // Register entity tuple maps in the current context
            this.session.RegisterEntityMap(typeof(Chosen), typeof(EtChosen));
            this.session.RegisterEntityMap(typeof(Context), typeof(EtContext));
            this.session.RegisterEntityMap(typeof(Count), typeof(EtCount));
            this.session.RegisterEntityMap(typeof(Guest), typeof(EtGuest));
            this.session.RegisterEntityMap(typeof(LastSeat), typeof(EtLastSeat));
            this.session.RegisterEntityMap(typeof(Path), typeof(EtPath));
            this.session.RegisterEntityMap(typeof(Seating), typeof(EtSeating));

            // Initialise selection dictionaries
            this.typeDictionary.Add(typeof(EtChosen), new SelectionTargets(this.trChosen, this.not2BFunc));
            this.typeDictionary.Add(typeof(EtContext), new SelectionTargets(this.contextStateFunc));
            this.typeDictionary.Add(typeof(EtCount), new SelectionTargets(this.trCount, this.join2BFunc, this.join6BFunc));
            this.typeDictionary.Add(typeof(EtGuest), new SelectionTargets(this.trGuest, this.join1BFunc, this.join4BFunc, this.join5BFunc));
            this.typeDictionary.Add(typeof(EtLastSeat), new SelectionTargets(this.trLastSeat, this.join9BFunc, this.join12BFunc));
            this.typeDictionary.Add(typeof(EtPath), new SelectionTargets(this.trPath, this.not1BFunc, this.join8BFunc, this.not3BFunc, this.join13BFunc));
            this.typeDictionary.Add(typeof(EtSeating), new SelectionTargets(this.trSeating, this.seatingPathDoneFunc, this.join10BFunc, this.join11BFunc));

            this.seatingPathDoneDictionary.Add("yes", new SelectionTargets(this.trSeatingYes, this.join3BFunc));
            this.seatingPathDoneDictionary.Add("no", new SelectionTargets(this.trSeatingNo, this.join7BFunc));

            this.contextStateDictionary.Add("start", new SelectionTargets(this.trContextStart, this.join1AFunc));
            this.contextStateDictionary.Add("assign_seats", new SelectionTargets(this.trContextAssignSeats, this.join3AFunc));
            this.contextStateDictionary.Add("make_path", new SelectionTargets(this.trContextMakePath, this.join7AFunc));
            this.contextStateDictionary.Add("check_done", new SelectionTargets(this.trContextCheckDone, this.join9AFunc, this.t6ContinueFunc));
            this.contextStateDictionary.Add("print_results", new SelectionTargets(this.trContextPrintResults, this.join11AFunc, this.t8AllDoneFunc));

            this.tvGuestName = this.trGuest.GetTupleView<string>(this.guestNameIndexer);
            this.tvChosenIdNameHobby = this.trChosen.GetTupleView<int>(this.chosenIdNameHobbyIndexer);
            this.tvPathIdName = this.trPath.GetTupleView<int>(this.pathIdNameIndexer);
            this.tvSeatingSeat2 = this.trSeating.GetTupleView<int>(this.seatingSeat2Indexer);
            this.tvLastSeatSeat = this.trLastSeat.GetTupleView<int>(this.lastSeatSeatIndexer);
            this.tvJSeq2J3SeatingName2 = this.trJ3.GetTupleView<string>(this.jSeq2J3SeatingName2Indexer);
            this.tvJSeq3J7SeatingPid = this.trJ7.GetTupleView<int>(this.jSeq3J7SeatingPidIndexer);
            this.tvJSeq4J9LastSeatingSeat = this.trJ9.GetTupleView<int>(this.jSeq4J9LastSeatingSeatIndexer);
            this.tvJSeq5J11SeatingSeat2 = this.trJ11.GetTupleView<int>(this.jSeq5J11SeatingSeat2Indexer);
            this.tvJSeq5J12SeatingId = this.trJ12.GetTupleView<int>(this.jSeq5J12SeatingIdIndexer);


            this.session.InitialMonadicFunctions = EvaluateType;
            this.quantifications = new bool[3];

            // register the Tuple types with the tuple pool
            TuplePool.RegisterTupleType(typeof(EtChosen));
            TuplePool.RegisterTupleType(typeof(EtContext));
            TuplePool.RegisterTupleType(typeof(EtCount));
            TuplePool.RegisterTupleType(typeof(EtGuest));
            TuplePool.RegisterTupleType(typeof(EtLastSeat));
            TuplePool.RegisterTupleType(typeof(EtPath));
            TuplePool.RegisterTupleType(typeof(EtSeating));
            TuplePool.RegisterTupleType(typeof(JoinRoot1));
            TuplePool.RegisterTupleType(typeof(JoinRoot2));
            TuplePool.RegisterTupleType(typeof(JoinRoot3));
            TuplePool.RegisterTupleType(typeof(JoinRoot4));
            TuplePool.RegisterTupleType(typeof(JoinRoot5));
            TuplePool.RegisterTupleType(typeof(J1));
            TuplePool.RegisterTupleType(typeof(J3));
            TuplePool.RegisterTupleType(typeof(J4));
            TuplePool.RegisterTupleType(typeof(J5));
            TuplePool.RegisterTupleType(typeof(J6));
            TuplePool.RegisterTupleType(typeof(J7));
            TuplePool.RegisterTupleType(typeof(J8));
            TuplePool.RegisterTupleType(typeof(J9));
            TuplePool.RegisterTupleType(typeof(J11));
            TuplePool.RegisterTupleType(typeof(J12));
            TuplePool.RegisterTupleType(typeof(AssignFirstSeat));
            TuplePool.RegisterTupleType(typeof(FindSeating));
            TuplePool.RegisterTupleType(typeof(AreWeDone));
            TuplePool.RegisterTupleType(typeof(Continue));
            TuplePool.RegisterTupleType(typeof(MakePath));
            TuplePool.RegisterTupleType(typeof(PathDone));
            TuplePool.RegisterTupleType(typeof(AllDone));
            TuplePool.RegisterTupleType(typeof(PrintResults));
        }

        public override void IncrementGeneration()
        {
            switch (this.j6TupleList == null)
            {
                case true:
                    this.j6TupleList = this.trJ6.GetTupleList(typeof(All));
                    break;
            }

            switch (this.j8TupleList == null)
            {
                case true:
                    this.j8TupleList = this.trJ8.GetTupleList(typeof(All));
                    break;
            }

            switch (this.j6TupleList == null)
            {
                case false:
                    DoIncrementGeneration(this.j6TupleList);
                    break;
            }

            switch (this.j8TupleList == null)
            {
                case false:
                    DoIncrementGeneration(this.j8TupleList);
                    break;
            }
        }

        #region Executor Primitives

        /// <summary>
        /// Represents a generated function
        /// </summary>
        /// <returns>An Executor monad</returns>
        private TupleList EvaluateType(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("EvaluateType");
            var tuple = tuples.First;

            // Create a new Tuple List here over a single value
            var newTupleList = new TupleList(tuple);

            SelectionTargets typeTargets;
#if EVAL_COUNTS
            MannersExecutor.IncrementEvalCount("          Evaluate Type: " + tuple.GetType().Name);
#endif

            // If type is recognised, then add the monadic functions
            switch (this.typeDictionary.TryGetValue(tuple.GetType(), out typeTargets))
            {
                case true:
                    switch (typeTargets.MonadicFunction == null)
                    {
                        case false:
                            foreach (MonadicFunction bf in typeTargets.MonadicFunction.GetInvocationList())
                            {
                                newTupleList.AddMonadicFunction(bf);
                            }
                            break;
                    }

                    var tr = typeTargets.TupleRelation;

                    switch (tr == null)
                    {
                        case false:
                            tr.AddTuple(tuple);
                            break;
                    }
                    break;
            }

            return newTupleList;
        }

        /// <summary>
        /// Represents a generated function
        /// </summary>
        /// <returns>An Executor monad</returns>
        private TupleList SeatingPathDone(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("SeatingPathDone");
            var tuple = tuples.First;

            // Create a new Tuple List here over a single value
            var newTupleList = new TupleList(tuple);

            SelectionTargets selectionTargets;

#if EVAL_COUNTS
            MannersExecutor.IncrementEvalCount("          Seating.PathDone: " + ((EtSeating)tuple).Seating_PathDone);
#endif

            // If type is recognised, then add the monadic function
            switch (this.seatingPathDoneDictionary.TryGetValue(((EtSeating)tuple).SeatingPathDone, out selectionTargets))
            {
                case true:
                    foreach (MonadicFunction bf in selectionTargets.MonadicFunction.GetInvocationList())
                    {
                        newTupleList.AddMonadicFunction(bf);
                    }

                    var tr = selectionTargets.TupleRelation;

                    switch (tr == null)
                    {
                        case false:
                            tr.AddTuple(tuple);
                            break;
                    }
                    break;
            }

            return newTupleList;
        }

        /// <summary>
        /// Represents a generated function
        /// </summary>
        /// <returns>An Executor monad</returns>
        private TupleList ContextState(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("ContextState");
            var tuple = tuples.First;

            // Create a new Tuple List here over a single value
            var newTupleList = new TupleList(tuple);

            SelectionTargets selectionTargets;

#if EVAL_COUNTS
            MannersExecutor.IncrementEvalCount("          Context.State: " + ((EtContext)tuple).Context_State);
#endif

            // If type is recognised, then add the monadic function
            switch (this.contextStateDictionary.TryGetValue(((EtContext)tuple).ContextState, out selectionTargets))
            {
                case true:
                    foreach (MonadicFunction bf in selectionTargets.MonadicFunction.GetInvocationList())
                    {
                        newTupleList.AddMonadicFunction(bf);
                    }

                    var tr = selectionTargets.TupleRelation;

                    switch (tr == null)
                    {
                        case false:
                            tr.AddTuple(tuple);
                            break;
                    }
                    break;
            }

            return newTupleList;
        }

        private TupleList Join1A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join1a");
            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.guestTupleList == null)
            {
                case true:
                    this.guestTupleList = this.trGuest.GetTupleList(typeof(All));
                    break;
            }

            switch (this.guestTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J1));

                    // Join tuples
                    EntityTuple tuple;

                    while (!((tuple = (EntityTuple)tuples.GetNext()) == null))
                    {
                        EntityTuple matchingTuple;
                        while (!((matchingTuple = (EntityTuple)this.guestTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J1>();

                            bNew.ContextFact = (Context)tuple.Fact;
                            bNew.GuestFact = (Guest)matchingTuple.Fact;

                            //bNew.CopyIdValues(tuple);
                            //bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ1.AddTuple(bNew);
                            tuplesOut.Add(bNew);
                        }

                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join2AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join1B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join1b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.contextStartTupleList == null)
            {
                case true:
                    this.contextStartTupleList = this.trContextStart.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.contextStartTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J1));

                    EntityTuple tuple;
                    while ((tuple = (EntityTuple)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;
                        while (!((matchingTuple = (EntityTuple)this.contextStartTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J1>();

                            bNew.GuestFact = (Guest)tuple.Fact;
                            bNew.ContextFact = (Context)matchingTuple.Fact;

                            ////bNew.CopyIdValues(tuple);
                            ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ1.AddTuple(bNew);
                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join2AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join2A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join2a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.countTupleList == null)
            {
                case true:
                    this.countTupleList = this.trCount.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.countTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(AssignFirstSeat));

                    J1 tuple;
                    while ((tuple = (J1)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;

                        while (!((matchingTuple = (EntityTuple)this.countTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<AssignFirstSeat>();

                            bNew.ContextFact = tuple.ContextFact;
                            bNew.GuestFact = tuple.GuestFact;
                            bNew.CountFact = (Count)matchingTuple.Fact;

                            //bNew.CopyIdValues(tuple);
                            //bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.t1AssignFirstSeatFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join2B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join2b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.j1TupleList == null)
            {
                case true:
                    this.j1TupleList = this.trJ1.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.j1TupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(AssignFirstSeat));

                    EntityTuple tuple;
                    while (!((tuple = (EntityTuple)tuples.GetNext()) == null))
                    {
                        J1 matchingTuple;

                        while (!((matchingTuple = (J1)this.j1TupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<AssignFirstSeat>();

                            bNew.CountFact = (Count)tuple.Fact;
                            bNew.ContextFact = matchingTuple.ContextFact;
                            bNew.GuestFact = matchingTuple.GuestFact;

                            //bNew.CopyIdValues(tuple);
                            //bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.t1AssignFirstSeatFunc);
                    break;
            }

            return newTupleList;
        }


        private TupleList Join6B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join6b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.j5TupleList == null)
            {
                case true:
                    this.j5TupleList = this.trJ5.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.j5TupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J6));

                    EntityTuple tuple;
                    while (!((tuple = (EntityTuple)tuples.GetNext()) == null))
                    {
                        J5 matchingTuple;

                        while (!((matchingTuple = (J5)this.j5TupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J6>();

                            bNew.CountFact = (Count)tuple.Fact;
                            bNew.ContextFact = matchingTuple.ContextFact;
                            bNew.SeatingFact = matchingTuple.SeatingFact;
                            bNew.Guest1Fact = matchingTuple.Guest1Fact;
                            bNew.Guest2Fact = matchingTuple.Guest2Fact;

                            //bNew.CopyIdValues(tuple);
                            //bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ6.AddTuple(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (!this.quantifications[0])
            {
                case true:
                    newTupleList.AddQuantificationMonadicFunction(this.not1AFunc);
                    this.quantifications[0] = true;
                    break;
            }

            return newTupleList;
        }

        private TupleList Join3A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join3a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.seatingYesTupleList == null)
            {
                case true:
                    this.seatingYesTupleList = this.trSeatingYes.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.seatingYesTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J3));

                    EntityTuple tuple;

                    while (!((tuple = (EntityTuple)tuples.GetNext()) == null))
                    {
                        EntityTuple matchingTuple;

                        while (!((matchingTuple = (EntityTuple)this.seatingYesTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J3>();

                            bNew.ContextFact = (Context)tuple.Fact;
                            bNew.SeatingFact = (Seating)matchingTuple.Fact;

                            ////bNew.CopyIdValues(tuple);
                            ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ3.AddTuple(bNew);
                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join4AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join3B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join3b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.contextAssignSeatTupleList == null)
            {
                case true:
                    this.contextAssignSeatTupleList = this.trContextAssignSeats.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.contextAssignSeatTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J3));

                    EntityTuple tuple;

                    while ((tuple = (EntityTuple)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;

                        while (!((matchingTuple = (EntityTuple)this.contextAssignSeatTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J3>();

                            bNew.SeatingFact = (Seating)tuple.Fact;
                            bNew.ContextFact = (Context)matchingTuple.Fact;

                            ////bNew.CopyIdValues(tuple);
                            ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ3.AddTuple(bNew);
                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join4AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join4A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join4a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            // Join tuples
            TuplePool.FixType(typeof(J4));

            J3 tuple;
            while ((tuple = (J3)tuples.GetNext()) != null)
            {
                var list = this.trGuest.GetTupleList(this.tvGuestName, tuple.SeatingName2);

                EntityTuple matchingTuple;

                while ((matchingTuple = (EntityTuple)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<J4>();

                    bNew.ContextFact = tuple.ContextFact;
                    bNew.SeatingFact = tuple.SeatingFact;
                    bNew.Guest1Fact = (Guest)matchingTuple.Fact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 1);
                    matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    this.trJ4.AddTuple(bNew);
                    tuplesOut.Add(bNew);
                }
            }

            TuplePool.UnfixType();


            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join5AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join4B(TupleMonadLinkedList tuples)
        {
            // List of tuples that will be output by join
            System.Diagnostics.Debug.WriteLine("Join4b");
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(J4));

            // Join tuples
            EntityTuple tuple;

            while ((tuple = (EntityTuple)tuples.GetNext()) != null)
            {
                var list = this.trJ3.GetTupleList(this.tvJSeq2J3SeatingName2, ((EtGuest)tuple).GuestName);

                J3 matchingTuple;

                while ((matchingTuple = (J3)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<J4>();

                    bNew.Guest1Fact = (Guest)tuple.Fact;
                    bNew.ContextFact = matchingTuple.ContextFact;
                    bNew.SeatingFact = matchingTuple.SeatingFact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 2);
                    matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    this.trJ4.AddTuple(bNew);
                    tuplesOut.Add(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join5AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join5A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join5a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(J5));

            // Join tuples
            J4 tuple;
            while ((tuple = (J4)tuples.GetNext()) != null)
            {
                var hsListNotSex = this.trGuest.GetNotTupleLists(this.guestSexHobbyIndexer, tuple.Guest1Sex);

                for (var idx = 0; idx < hsListNotSex.Count; idx++)
                {
                    var listNotSexHobby = this.trGuest.GetTupleList(hsListNotSex[idx].NestedTupleView, tuple.Guest1Hobby);

                    EntityTuple matchingTuple;
                    while (!((matchingTuple = (EntityTuple)listNotSexHobby.Next()) == null))
                    {
                        var bNew = TuplePool.GetItem<J5>();

                        bNew.ContextFact = tuple.ContextFact;
                        bNew.SeatingFact = tuple.SeatingFact;
                        bNew.Guest1Fact = tuple.Guest1Fact;
                        bNew.Guest2Fact = (Guest)matchingTuple.Fact;

                        ////bNew.CopyIdValues(tuple);
                        ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                        tuple.RegisterSubsumerTuple(bNew);
                        matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                        this.trJ5.AddTuple(bNew);
                        tuplesOut.Add(bNew);
                    }
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join6AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join5B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join5b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(J5));

            // Join tuples
            EntityTuple tuple;
            while ((tuple = (EntityTuple)tuples.GetNext()) != null)
            {
                var hsListNotSex = this.trJ4.GetNotTupleLists(this.jSeq2J4GuestSexHobbyIndexer, ((EtGuest)tuple).GuestSex);

                for (var idx = 0; idx < hsListNotSex.Count; idx++)
                {
                    var listNotSexHobby = this.trJ4.GetTupleList(hsListNotSex[idx].NestedTupleView, ((EtGuest)tuple).GuestHobby);

                    J4 matchingTuple;
                    while ((matchingTuple = (J4)listNotSexHobby.Next()) != null)
                    {
                        var bNew = TuplePool.GetItem<J5>();

                        bNew.Guest2Fact = (Guest)tuple.Fact;
                        bNew.ContextFact = matchingTuple.ContextFact;
                        bNew.SeatingFact = matchingTuple.SeatingFact;
                        bNew.Guest1Fact = matchingTuple.Guest1Fact;

                        ////bNew.CopyIdValues(tuple);
                        ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                        tuple.RegisterSubsumerTuple(bNew);
                        matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                        this.trJ5.AddTuple(bNew);
                        tuplesOut.Add(bNew);
                    }
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join6AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join6A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join6a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.countTupleList == null)
            {
                case true:
                    this.countTupleList = this.trCount.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.countTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J6));

                    J5 tuple;

                    while ((tuple = (J5)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;
                        while (!((matchingTuple = (EntityTuple)this.countTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J6>();

                            bNew.ContextFact = tuple.ContextFact;
                            bNew.SeatingFact = tuple.SeatingFact;
                            bNew.Guest1Fact = tuple.Guest1Fact;
                            bNew.Guest2Fact = tuple.Guest2Fact;
                            bNew.CountFact = (Count)matchingTuple.Fact;

                            ////bNew.CopyIdValues(tuple);
                            ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ6.AddTuple(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (!this.quantifications[0])
            {
                case true:
                    newTupleList.AddQuantificationMonadicFunction(this.not1AFunc);
                    this.quantifications[0] = true;
                    break;
            }

            return newTupleList;
        }

        ////////        private TupleList Join6b(TupleMonadLinkedList tuples)
        ////////        {
        ////////            // List of tuples that will be output by join
        ////////            TupleMonadLinkedList tuplesOut = new TupleMonadLinkedList();

        ////////            switch (_j5TupleList == null)
        ////////            {
        ////////                case true:
        ////////                    _j5TupleList = this._tr_J5.GetTupleList(typeof(All));
        ////////                    break;
        ////////            }

        ////////            // Join tuples
        ////////            switch (_j5TupleList == null)
        ////////            {
        ////////                case false:
        ////////                    TuplePool.FixType(typeof(J6));

        ////////                    EntityTuple tuple;
        ////////                    while (!((tuple = (EntityTuple)tuples.Next()) == null))
        ////////                    {
        ////////                        ////////// Add to memory as part of single 'transaction'
        ////////                        ////////this._tr_J5.AddTuple(tuple);

        ////////                        J5 matchingTuple;

        ////////                        while (!((matchingTuple = (J5)_j5TupleList.Next()) == null))
        ////////                        {
        ////////                            J6 bNew = TuplePool.GetItem<J6>();

        ////////                            bNew.CountFact = (Count)tuple.Fact;
        ////////                            bNew.ContextFact = matchingTuple.ContextFact;
        ////////                            bNew.SeatingFact = matchingTuple.SeatingFact;
        ////////                            bNew.Guest1Fact = matchingTuple.Guest1Fact;
        ////////                            bNew.Guest2Fact = matchingTuple.Guest2Fact;

        ////////                            //bNew.CopyIdValues(tuple);
        ////////                            //bNew.CopyIdValues(matchingTuple);

        ////////#if FULL_ASYMMETRIC_RETRACT
        ////////                        tuple.RegisterSubsumerTuple(bNew, 2);
        ////////                        matchingTuple.RegisterSubsumerTuple(bNew, 1);
        ////////#else
        ////////                            tuple.RegisterSubsumerTuple(bNew);
        ////////                            matchingTuple.RegisterSubsumerTuple(bNew);
        ////////#endif

        ////////                            // Add to memory - done 'early' because next func is delayed
        ////////                            this._tr_J6.AddTuple(bNew);
        ////////                        }
        ////////                    }

        ////////                    TuplePool.UnfixType();
        ////////                    break;
        ////////            }

        ////////            // Create a new Monad here
        ////////            TupleList newTupleList = new TupleList(tuplesOut);

        ////////            switch (!notFlags[0])
        ////////            {
        ////////                case true:
        ////////                    newTupleList.AddQuantificationMonadicFunction(_not1aFunc);
        ////////                    notFlags[0] = true;
        ////////                    break;
        ////////            }

        ////////            return newTupleList;
        ////////        }

        private TupleList Not1A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Not1a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.j6TupleList == null)
            {
                case true:
                    this.j6TupleList = this.trJ6.GetTupleList(typeof(All));
                    break;
            }


            // Join tuples
            switch (this.j6TupleList == null)
            {
                case false:
                    J6 tuple;
                    while (!((tuple = (J6)this.j6TupleList.Next()) == null))
                    {
                        var list = this.trPath.GetTupleList(this.tvPathIdName, tuple.SeatingId);
                        var gen0 = (tuple.Generation == 0);

                        switch (list.Count > 0)
                        {
                            case true:
                                list = this.trPath.GetTupleList(list.NestedTupleView, tuple.Guest2Name);

                                switch (list.Count > 0)
                                {
                                    case true:

                                        switch (tuple.Generation > 0)
                                        {
                                            case true:
                                                // Get match on gen0
                                                list.Mode = TupleLinkedListMode.Gen0Only;
                                                gen0 = true;
                                                break;
                                        }
                                        break;
                                }
                                break;
                        }

                        if (list.Count == 0 && gen0)
                        {
                            tuplesOut.Add(tuple);
                        }
                    }
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            if (tuplesOut.Count > 0 && !this.quantifications[1])
            {
                newTupleList.AddQuantificationMonadicFunction(this.not2AFunc);
                this.quantifications[1] = true;
            }

            return newTupleList;

        }

        private TupleList Not1B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Not1b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            var newTupleList = new TupleList(tuplesOut);

            switch (!this.quantifications[0])
            {
                case true:
                    newTupleList.AddQuantificationMonadicFunction(this.not1AFunc);
                    this.quantifications[0] = true;
                    break;
            }

            return newTupleList;
        }

        private TupleList Not2A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Not2a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(FindSeating));

            J6 tuple;
            while ((tuple = (J6)tuples.GetNext()) != null)
            {
                var list = this.trChosen.GetTupleList(this.tvChosenIdNameHobby, tuple.SeatingId);
                var gen0 = (tuple.Generation == 0);

                switch (list.Count > 0)
                {
                    case true:
                        list = this.trChosen.GetTupleList(list.NestedTupleView, tuple.Guest2Name);

                        switch (list.Count > 0)
                        {
                            case true:
                                list = this.trChosen.GetTupleList(list.NestedTupleView, tuple.Guest1Hobby);

                                switch (list.Count > 0)
                                {
                                    case true:
                                        switch (tuple.Generation > 0)
                                        {
                                            case true:
                                                // Get match on gen0
                                                list.Mode = TupleLinkedListMode.Gen0Only;
                                                gen0 = true;
                                                break;
                                        }
                                        break;
                                }
                                break;
                        }
                        break;
                }

                switch (list.Count == 0 && gen0)
                {
                    case true:
                        var bNew = TuplePool.GetItem<FindSeating>();

                        bNew.ContextFact = tuple.ContextFact;
                        bNew.CountFact = tuple.CountFact;
                        bNew.Guest1Fact = tuple.Guest1Fact;
                        bNew.Guest2Fact = tuple.Guest2Fact;
                        bNew.SeatingFact = tuple.SeatingFact;

                        //bNew.CopyIdValues(tuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 1);
#else
                        tuple.RegisterSubsumerTuple(bNew);
#endif
                        tuplesOut.Add(bNew);
                        break;
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.t2FindSeatingFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Not2B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Not2b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            var newTupleList = new TupleList(tuplesOut);

            switch (!this.quantifications[1])
            {
                case true:
                    newTupleList.AddQuantificationMonadicFunction(this.not2AFunc);
                    this.quantifications[1] = true;
                    break;
            }


            return newTupleList;
        }

        private TupleList Join7A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join7a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.seatingNoTupleList == null)
            {
                case true:
                    this.seatingNoTupleList = this.trSeatingNo.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.seatingNoTupleList == null)
            {
                case false:
                    EntityTuple tuple;

                    while ((tuple = (EntityTuple)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;

                        while (!((matchingTuple = (EntityTuple)this.seatingNoTupleList.Next()) == null))
                        {
                            var bNew1 = TuplePool.GetItem<J7>();

                            bNew1.ContextFact = (Context)tuple.Fact;
                            bNew1.SeatingFact = (Seating)matchingTuple.Fact;

                            ////bNew1.CopyIdValues(tuple);
                            ////bNew1.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew1, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew1, 2);
#else
                            tuple.RegisterSubsumerTuple(bNew1);
                            matchingTuple.RegisterSubsumerTuple(bNew1);
#endif

                            this.trJ7.AddTuple(bNew1);
                            tuplesOut.Add(bNew1);

                            var bNew2 = TuplePool.GetItem<PathDone>();

                            bNew2.ContextFact = (Context)tuple.Fact;
                            bNew2.SeatingFact = (Seating)matchingTuple.Fact;

                            ////bNew2.CopyIdValues(tuple);
                            ////bNew2.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew2, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew2, 2);
#else
                            tuple.RegisterSubsumerTuple(bNew2);
                            matchingTuple.RegisterSubsumerTuple(bNew2);
#endif

                            tuplesOut.Add(bNew2);
                        }
                    }
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join8AFunc);
                    newTupleList.AddMonadicFunction(this.t4PathDoneFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join7B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join7b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.contextMakePathTupleList == null)
            {
                case true:
                    this.contextMakePathTupleList = this.trContextMakePath.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.contextMakePathTupleList == null)
            {
                case false:
                    EntityTuple tuple;
                    while (!((tuple = (EntityTuple)tuples.GetNext()) == null))
                    {
                        EntityTuple matchingTuple;

                        while (!((matchingTuple = (EntityTuple)this.contextMakePathTupleList.Next()) == null))
                        {
                            var bNew1 = TuplePool.GetItem<J7>();

                            bNew1.SeatingFact = (Seating)tuple.Fact;
                            bNew1.ContextFact = (Context)matchingTuple.Fact;

                            ////bNew1.CopyIdValues(tuple);
                            ////bNew1.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew1, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew1, 1);
#else
                            tuple.RegisterSubsumerTuple(bNew1);
                            matchingTuple.RegisterSubsumerTuple(bNew1);
#endif

                            this.trJ7.AddTuple(bNew1);
                            tuplesOut.Add(bNew1);

                            var bNew2 = TuplePool.GetItem<PathDone>();

                            bNew2.SeatingFact = (Seating)tuple.Fact;
                            bNew2.ContextFact = (Context)matchingTuple.Fact;

                            ////bNew2.CopyIdValues(tuple);
                            ////bNew2.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew2, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew2, 1);
#else
                            tuple.RegisterSubsumerTuple(bNew2);
                            matchingTuple.RegisterSubsumerTuple(bNew2);
#endif

                            tuplesOut.Add(bNew2);
                        }
                    }
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join8AFunc);
                    newTupleList.AddMonadicFunction(this.t4PathDoneFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join8A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join8a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(J8));

            // Join tuples
            J7 tuple;
            while (!((tuple = (J7)tuples.GetNext(typeof(J7))) == null))
            {
                var list = this.trPath.GetTupleList(this.tvPathIdName, tuple.SeatingPid);

                EntityTuple matchingTuple;

                while ((matchingTuple = (EntityTuple)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<J8>();

                    bNew.ContextFact = tuple.ContextFact;
                    bNew.SeatingFact = tuple.SeatingFact;
                    bNew.PathFact = (Path)matchingTuple.Fact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 1);
                    matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    this.trJ8.AddTuple(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (!this.quantifications[2])
            {
                case true:
                    newTupleList.AddQuantificationMonadicFunction(this.not3AFunc);
                    this.quantifications[2] = true;
                    break;
            }


            return newTupleList;
        }

        private TupleList Join8B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join8b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(J8));

            // Join tuples
            EntityTuple tuple;
            while ((tuple = (EntityTuple)tuples.GetNext()) != null)
            {
                var list = this.trJ7.GetTupleList(this.tvJSeq3J7SeatingPid, ((EtPath)tuple).PathId);

                J7 matchingTuple;
                while ((matchingTuple = (J7)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<J8>();

                    bNew.PathFact = (Path)tuple.Fact;
                    bNew.ContextFact = matchingTuple.ContextFact;
                    bNew.SeatingFact = matchingTuple.SeatingFact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 2);
                    matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    this.trJ8.AddTuple(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (!this.quantifications[2])
            {
                case true:
                    newTupleList.AddQuantificationMonadicFunction(this.not3AFunc);
                    this.quantifications[2] = true;
                    break;
            }

            return newTupleList;
        }

        private TupleList Not3A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Not3a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.j8TupleList == null)
            {
                case true:
                    this.j8TupleList = this.trJ8.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.j8TupleList == null)
            {
                case false:

                    TuplePool.FixType(typeof(MakePath));

                    J8 tuple;
                    while (!((tuple = (J8)this.j8TupleList.Next()) == null))
                    {
                        var list = this.trPath.GetTupleList(this.tvPathIdName, tuple.SeatingId);
                        var gen0 = tuple.Generation == 0;

                        switch (list.Count > 0)
                        {
                            case true:
                                list = this.trPath.GetTupleList(list.NestedTupleView, tuple.PathName);

                                switch (list.Count > 0)
                                {
                                    case true:
                                        switch (tuple.Generation > 0)
                                        {
                                            case true:
                                                // Get match on gen0
                                                list.Mode = TupleLinkedListMode.Gen0Only;
                                                gen0 = true;
                                                break;
                                        }
                                        break;
                                }
                                break;
                        }

                        switch (list.Count == 0 && gen0)
                        {
                            case true:
                                var bNew = TuplePool.GetItem<MakePath>();

                                bNew.ContextFact = tuple.ContextFact;
                                bNew.PathFact = tuple.PathFact;
                                bNew.SeatingFact = tuple.SeatingFact;

                                ////bNew.CopyIdValues(tuple);

#if FULL_ASYMMETRIC_RETRACT
                                tuple.RegisterSubsumerTuple(bNew, 1);
#else
                                tuple.RegisterSubsumerTuple(bNew);
#endif
                                tuplesOut.Add(bNew);
                                break;

                        }
                    }

                    TuplePool.UnfixType();
                    break;

            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.t3MakePathFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Not3B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Not3b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            var newTupleList = new TupleList(tuplesOut);

            switch (!this.quantifications[2])
            {
                case true:
                    newTupleList.AddQuantificationMonadicFunction(this.not3AFunc);
                    this.quantifications[2] = true;
                    break;
            }


            return newTupleList;
        }

        private TupleList Join9A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join9a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.lastSeatTupleList == null)
            {
                case true:
                    this.lastSeatTupleList = this.trLastSeat.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.lastSeatTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J9));

                    EntityTuple tuple;

                    while ((tuple = (EntityTuple)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;

                        while (!((matchingTuple = (EntityTuple)this.lastSeatTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J9>();

                            bNew.ContextFact = (Context)tuple.Fact;
                            bNew.LastSeatFact = (LastSeat)matchingTuple.Fact;

                            ////bNew.CopyIdValues(tuple);
                            ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ9.AddTuple(bNew);
                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join10AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join9B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join9b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.contextCheckDoneTupleList == null)
            {
                case true:
                    this.contextCheckDoneTupleList = this.trContextCheckDone.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.contextCheckDoneTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J9));

                    EntityTuple tuple;

                    while ((tuple = (EntityTuple)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;
                        while (!((matchingTuple = (EntityTuple)this.contextCheckDoneTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J9>();

                            bNew.LastSeatFact = (LastSeat)tuple.Fact;
                            bNew.ContextFact = (Context)matchingTuple.Fact;

                            ////bNew.CopyIdValues(tuple);
                            ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ9.AddTuple(bNew);
                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join10AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join10A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join10a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            // Join tuples
            TuplePool.FixType(typeof(AreWeDone));

            J9 tuple;
            while ((tuple = (J9)tuples.GetNext()) != null)
            {
                var list = this.trSeating.GetTupleList(this.tvSeatingSeat2, tuple.LastSeatSeat);

                EntityTuple matchingTuple;
                while ((matchingTuple = (EntityTuple)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<AreWeDone>();

                    bNew.ContextFact = tuple.ContextFact;
                    bNew.LastSeatFact = tuple.LastSeatFact;
                    bNew.SeatingFact = (Seating)matchingTuple.Fact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 1);
                    matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    tuplesOut.Add(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.t5AreWeDoneFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join10B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join10b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            // Join tuples
            TuplePool.FixType(typeof(AreWeDone));

            EntityTuple tuple;
            while ((tuple = (EntityTuple)tuples.GetNext()) != null)
            {
                var list = this.trJ9.GetTupleList(this.tvJSeq4J9LastSeatingSeat, ((EtSeating)tuple).SeatingSeat2);

                J9 matchingTuple;

                while ((matchingTuple = (J9)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<AreWeDone>();

                    bNew.SeatingFact = (Seating)tuple.Fact;
                    bNew.ContextFact = matchingTuple.ContextFact;
                    bNew.LastSeatFact = matchingTuple.LastSeatFact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 2);
                    matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    tuplesOut.Add(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.t5AreWeDoneFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join11A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join11a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.seatingTupleList == null)
            {
                case true:
                    this.seatingTupleList = this.trSeating.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.seatingTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J11));

                    EntityTuple tuple;

                    while ((tuple = (EntityTuple)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;

                        while (!((matchingTuple = (EntityTuple)this.seatingTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J11>();

                            bNew.ContextFact = (Context)tuple.Fact;
                            bNew.SeatingFact = (Seating)matchingTuple.Fact;

                            ////bNew.CopyIdValues(tuple);
                            ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 1);
                        matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ11.AddTuple(bNew);
                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;
            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join12AFunc);
                    break;
            }

            return newTupleList;

        }

        private TupleList Join11B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join11b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            switch (this.contextPrintResultsTupleList == null)
            {
                case true:
                    this.contextPrintResultsTupleList = this.trContextPrintResults.GetTupleList(typeof(All));
                    break;
            }

            // Join tuples
            switch (this.contextPrintResultsTupleList == null)
            {
                case false:
                    TuplePool.FixType(typeof(J11));

                    EntityTuple tuple;

                    while ((tuple = (EntityTuple)tuples.GetNext()) != null)
                    {
                        EntityTuple matchingTuple;

                        while (!((matchingTuple = (EntityTuple)this.contextPrintResultsTupleList.Next()) == null))
                        {
                            var bNew = TuplePool.GetItem<J11>();

                            bNew.SeatingFact = (Seating)tuple.Fact;
                            bNew.ContextFact = (Context)matchingTuple.Fact;

                            ////bNew.CopyIdValues(tuple);
                            ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                        tuple.RegisterSubsumerTuple(bNew, 2);
                        matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                            tuple.RegisterSubsumerTuple(bNew);
                            matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                            this.trJ11.AddTuple(bNew);
                            tuplesOut.Add(bNew);
                        }
                    }

                    TuplePool.UnfixType();
                    break;

            }

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join12AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join12A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join12a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(J12));

            // Join tuples
            J11 tuple;
            while (!((tuple = (J11)tuples.GetNext()) == null))
            {
                var list = this.trLastSeat.GetTupleList(this.tvLastSeatSeat, tuple.SeatingSeat2);

                EntityTuple matchingTuple;

                while ((matchingTuple = (EntityTuple)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<J12>();

                    bNew.ContextFact = tuple.ContextFact;
                    bNew.SeatingFact = tuple.SeatingFact;
                    bNew.LastSeatFact = (LastSeat)matchingTuple.Fact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 1);
                    matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    this.trJ12.AddTuple(bNew);
                    tuplesOut.Add(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join13AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join12B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join12b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(J12));

            // Join tuples
            EntityTuple tuple;
            while ((tuple = (EntityTuple)tuples.GetNext()) != null)
            {
                var list = this.trJ11.GetTupleList(this.tvJSeq5J11SeatingSeat2, ((EtLastSeat)tuple).LastSeatSeat);

                J12 matchingTuple;

                while ((matchingTuple = (J12)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<J12>();

                    bNew.LastSeatFact = (LastSeat)tuple.Fact;
                    bNew.SeatingFact = matchingTuple.SeatingFact;
                    bNew.ContextFact = matchingTuple.ContextFact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 2);
                    matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    this.trJ12.AddTuple(bNew);
                    tuplesOut.Add(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.join13AFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join13A(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join13a");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(PrintResults));

            // Join tuples
            J12 tuple;

            while ((tuple = (J12)tuples.GetNext()) != null)
            {
                var list = this.trPath.GetTupleList(this.tvPathIdName, tuple.SeatingId);

                EntityTuple matchingTuple;
                while ((matchingTuple = (EntityTuple)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<PrintResults>();

                    bNew.ContextFact = tuple.ContextFact;
                    bNew.LastSeatFact = tuple.LastSeatFact;
                    bNew.SeatingFact = tuple.SeatingFact;
                    bNew.PathFact = (Path)matchingTuple.Fact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 1);
                    matchingTuple.RegisterSubsumerTuple(bNew, 2);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    tuplesOut.Add(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.t7PrintResultsFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList Join13B(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("Join13b");

            // List of tuples that will be output by join
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(PrintResults));

            // Join tuples
            EntityTuple tuple;

            while ((tuple = (EntityTuple)tuples.GetNext()) != null)
            {
                var list = this.trJ12.GetTupleList(this.tvJSeq5J12SeatingId, ((EtPath)tuple).PathId);

                J12 matchingTuple;

                while ((matchingTuple = (J12)list.Next()) != null)
                {
                    var bNew = TuplePool.GetItem<PrintResults>();

                    bNew.PathFact = (Path)tuple.Fact;
                    bNew.ContextFact = matchingTuple.ContextFact;
                    bNew.LastSeatFact = matchingTuple.LastSeatFact;
                    bNew.SeatingFact = matchingTuple.SeatingFact;

                    ////bNew.CopyIdValues(tuple);
                    ////bNew.CopyIdValues(matchingTuple);

#if FULL_ASYMMETRIC_RETRACT
                    tuple.RegisterSubsumerTuple(bNew, 2);
                    matchingTuple.RegisterSubsumerTuple(bNew, 1);
#else
                    tuple.RegisterSubsumerTuple(bNew);
                    matchingTuple.RegisterSubsumerTuple(bNew);
#endif

                    tuplesOut.Add(bNew);
                }
            }

            TuplePool.UnfixType();

            // Create a new Monad here
            var newTupleList = new TupleList(tuplesOut);

            switch (tuplesOut.Count > 0)
            {
                case true:
                    newTupleList.AddMonadicFunction(this.t7PrintResultsFunc);
                    break;
            }

            return newTupleList;
        }

        private TupleList T1AssignFirstSeat(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("T1_AssignFirstSeat");
            Tuple tuple;

            while ((tuple = tuples.GetNext()) != null)
            {
                this.agendaPriority0.Push(tuple);
            }

            var newTupleList = new TupleList(tuples);
            return newTupleList;
        }

        private TupleList T2FindSeating(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("T2_FindSeating");
            Tuple tuple;

            while ((tuple = tuples.GetNext()) != null)
            {
                this.agendaPriority0.Push(tuple);
            }

            var newTupleList = new TupleList(tuples);
            return newTupleList;
        }

        private TupleList T3MakePath(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("T3_MakePath");
            Tuple tuple;

            while ((tuple = tuples.GetNext()) != null)
            {
                this.agendaPriority1.Push(tuple);
            }

            var newTupleList = new TupleList(tuples);
            return newTupleList;
        }

        private TupleList T4PathDone(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("T4_PathDone");
            Tuple tuple;

            while ((tuple = tuples.GetNext(typeof(PathDone))) != null)
            {
                this.agendaPriority0.Push(tuple);
            }

            var newTupleList = new TupleList(tuples);
            return newTupleList;
        }

        private TupleList T5AreWeDone(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("T5_AreWeDone");
            Tuple tuple;

            while ((tuple = tuples.GetNext()) != null)
            {
                this.agendaPriority1.Push(tuple);
            }

            var newTupleList = new TupleList(tuples);
            return newTupleList;
        }

        private TupleList T6Continue(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("T6_Continue");
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(Continue));

            EntityTuple tuple;

            while ((tuple = (EntityTuple)tuples.GetNext()) != null)
            {
                var bNew = TuplePool.GetItem<Continue>();

                bNew.ContextFact = (Context)tuple.Fact;
                ////bNew.CopyIdValues(tuple);
#if FULL_ASYMMETRIC_RETRACT
                tuple.RegisterSubsumerTuple(bNew, 1);
#else
                tuple.RegisterSubsumerTuple(bNew);
#endif


                tuplesOut.Add(bNew);
                this.agendaPriority0.Push(bNew);
            }

            TuplePool.UnfixType();

            var newTupleList = new TupleList(tuplesOut);
            return newTupleList;
        }

        private TupleList T7PrintResults(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("T7_PrintResults");
            Tuple tuple;

            while ((tuple = tuples.GetNext()) != null)
            {
                this.agendaPriority1.Push(tuple);
            }

            var newTupleList = new TupleList(tuples);
            return newTupleList;
        }

        private TupleList T8AllDone(TupleMonadLinkedList tuples)
        {
            System.Diagnostics.Debug.WriteLine("T8_AllDone");
            var tuplesOut = new TupleMonadLinkedList();

            TuplePool.FixType(typeof(AllDone));

            EntityTuple tuple;
            while ((tuple = (EntityTuple)tuples.GetNext()) != null)
            {
                var bNew = TuplePool.GetItem<AllDone>();

                bNew.ContextFact = (Context)tuple.Fact;
                ////bNew.CopyIdValues(tuple);
#if FULL_ASYMMETRIC_RETRACT
                tuple.RegisterSubsumerTuple(bNew, 1);
#else
                tuple.RegisterSubsumerTuple(bNew);
#endif

                tuplesOut.Add(bNew);
                this.agendaPriority0.Push(bNew);
            }

            TuplePool.UnfixType();

            var newTupleList = new TupleList(tuplesOut);
            return newTupleList;
        }

        #endregion Executor Primitives

        public class EtChosen : EntityTuple
        {
            private int chosenId;
            private string chosenName;
            private string chosenHobby;
            private bool cacheChosenId;
            private bool cacheChosenName;
            private bool cacheChosenHobby;

            private EtChosen prev30ChosenId;
            private EtChosen next30ChosenId;
            private EtChosen prev31ChosenName;
            private EtChosen next31ChosenName;
            private EtChosen prev32ChosenHobby;
            private EtChosen next32ChosenHobby;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next30ChosenId;
                    case 1:
                        return this.next31ChosenName;
                    case 2:
                        return this.next32ChosenHobby;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev30ChosenId;
                    case 1:
                        return this.prev31ChosenName;
                    case 2:
                        return this.prev32ChosenHobby;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next30ChosenId = (EtChosen)tuple;
                        break;
                    case 1:
                        this.next31ChosenName = (EtChosen)tuple;
                        break;
                    case 2:
                        this.next32ChosenHobby = (EtChosen)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev30ChosenId = (EtChosen)tuple;
                        break;
                    case 1:
                        this.prev31ChosenName = (EtChosen)tuple;
                        break;
                    case 2:
                        this.prev32ChosenHobby = (EtChosen)tuple;
                        break;
                }
            }

            public int ChosenId
            {
                get
                {
                    switch (!this.cacheChosenId)
                    {
                        case true:
                            SetCache("Chosen_Id");
                            break;
                    }

                    return this.chosenId;
                }

                set
                {
                    this.chosenId = value;
                    this.cacheChosenId = true;
                    AddToCacheRemovalList("Chosen_Id");
                }
            }

            public string ChosenName
            {
                get
                {
                    switch (!this.cacheChosenName)
                    {
                        case true:
                            SetCache("Chosen_Name");
                            break;
                    }

                    return this.chosenName;
                }

                set
                {
                    this.chosenName = value;
                    this.cacheChosenName = true;
                    AddToCacheRemovalList("Chosen_Name");
                }
            }

            public string ChosenHobby
            {
                get
                {
                    switch (!this.cacheChosenHobby)
                    {
                        case true:
                            SetCache("Chosen_Hobby");
                            break;
                    }

                    return this.chosenHobby;
                }

                set
                {
                    this.chosenHobby = value;
                    this.cacheChosenHobby = true;
                    AddToCacheRemovalList("Chosen_Hobby");
                }
            }

            public override object Fact
            {
                get
                {
                    return base.Fact;
                }

                set
                {
                    base.Fact = value;

                    switch (IsINotifyPropertyChanged(value))
                    {
                        case true:
                            ((System.ComponentModel.INotifyPropertyChanged)value).PropertyChanged += this.BoundFactPropertyChanged;
                            break;
                    }

                    this.SetCache();  // Only want to do this if there is anything cacheable and not lazy eval
                }
            }

            protected override void SetCache()
            {
                this.ChosenId = ((Chosen)this.Fact).Id;
                this.ChosenName = ((Chosen)this.Fact).Name;
                this.ChosenHobby = ((Chosen)this.Fact).Hobby;
                this.cacheChosenId = true;
                this.cacheChosenName = true;
                this.cacheChosenHobby = true;
            }

            protected override void SetCache(string memberName)
            {
                switch (memberName)
                {
                    case "Chosen_Id":
                        this.ChosenId = ((Chosen)this.Fact).Id;
                        this.cacheChosenId = true;
                        break;
                    case "Chosen_Name":
                        this.ChosenName = ((Chosen)this.Fact).Name;
                        this.cacheChosenName = true;
                        break;
                    case "Chosen_Hobby":
                        this.ChosenHobby = ((Chosen)this.Fact).Hobby;
                        this.cacheChosenHobby = true;
                        break;
                }
            }

            public override void UpdateFact()
            {
                foreach (var memberName in this.cacheRemovalList)
                {
                    switch (memberName)
                    {
                        case "Chosen_Id":
                            ((Chosen)this.Fact).Id = this.ChosenId;
                            break;
                        case "Chosen_Name":
                            ((Chosen)this.Fact).Name = this.ChosenName;
                            break;
                        case "Chosen_Hobby":
                            ((Chosen)this.Fact).Hobby = this.ChosenHobby;
                            break;
                    }
                }

                this.cacheRemovalList.Clear();
            }

            // TODO:   Not yet generating code for this
            public override void Clear()
            {
                base.Clear();

                this.chosenId = new int();
                this.chosenName = null;
                this.chosenHobby = null;

                this.cacheChosenId
              = this.cacheChosenName
              = this.cacheChosenHobby = false;

                this.prev30ChosenId
              = this.next30ChosenId
              = this.prev31ChosenName
              = this.next31ChosenName
              = this.prev32ChosenHobby
              = this.next32ChosenHobby = null;
            }
        }

        public class EtContext : EntityTuple
        {
            private string contextState;
            private bool cacheContextState;

            private EtContext prev60ContextStart;
            private EtContext next60ContextStart;
            private EtContext prev70ContextAssignSeats;
            private EtContext next70ContextAssignSeats;
            private EtContext prev80ContextMakePath;
            private EtContext next80ContextMakePath;
            private EtContext prev90ContextCheckDone;
            private EtContext next90ContextCheckDone;
            private EtContext prev100ContextPrintResults;
            private EtContext next100ContextPrintResults;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next60ContextStart;
                    case 1:
                        return this.next70ContextAssignSeats;
                    case 2:
                        return this.next80ContextMakePath;
                    case 3:
                        return this.next90ContextCheckDone;
                    case 4:
                        return this.next100ContextPrintResults;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev60ContextStart;
                    case 1:
                        return this.prev70ContextAssignSeats;
                    case 2:
                        return this.prev80ContextMakePath;
                    case 3:
                        return this.prev90ContextCheckDone;
                    case 4:
                        return this.prev100ContextPrintResults;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next60ContextStart = (EtContext)tuple;
                        break;
                    case 1:
                        this.next70ContextAssignSeats = (EtContext)tuple;
                        break;
                    case 2:
                        this.next80ContextMakePath = (EtContext)tuple;
                        break;
                    case 3:
                        this.next90ContextCheckDone = (EtContext)tuple;
                        break;
                    case 4:
                        this.next100ContextPrintResults = (EtContext)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev60ContextStart = (EtContext)tuple;
                        break;
                    case 1:
                        this.prev70ContextAssignSeats = (EtContext)tuple;
                        break;
                    case 2:
                        this.prev80ContextMakePath = (EtContext)tuple;
                        break;
                    case 3:
                        this.prev90ContextCheckDone = (EtContext)tuple;
                        break;
                    case 4:
                        this.prev100ContextPrintResults = (EtContext)tuple;
                        break;
                }
            }

            public string ContextState
            {
                get
                {
                    switch (!this.cacheContextState)
                    {
                        case true:
                            SetCache("ContextState");
                            break;
                    }

                    return this.contextState;

                }

                set
                {
                    this.contextState = value;
                    this.cacheContextState = true;
                    AddToCacheRemovalList("ContextState");
                }
            }

            public override object Fact
            {
                get
                {
                    return base.Fact;
                }

                set
                {
                    base.Fact = value;

                    switch (IsINotifyPropertyChanged(value))
                    {
                        case true:
                            ((System.ComponentModel.INotifyPropertyChanged)value).PropertyChanged += this.BoundFactPropertyChanged;
                            break;
                    }

                    this.SetCache();  // Only want to do this if there is anything cacheable and not lazy eval
                }
            }

            protected override void SetCache()
            {
                this.ContextState = Context.State;
                this.cacheContextState = true;
            }

            protected override void SetCache(string memberName)
            {
                switch (memberName)
                {
                    case "ContextState":
                        this.ContextState = Context.State;
                        this.cacheContextState = true;
                        break;
                }
            }

            public override void UpdateFact()
            {
                foreach (var memberName in this.cacheRemovalList)
                {
                    switch (memberName)
                    {
                        case "ContextState":
                            Context.State = this.ContextState;
                            break;
                    }
                }

                this.cacheRemovalList.Clear();
            }

            // TODO:   Not yet generating code for this
            public override void Clear()
            {
                base.Clear();

                this.contextState = default(string);

                this.cacheContextState = false;

                this.prev60ContextStart
              = this.next60ContextStart
              = this.prev70ContextAssignSeats
              = this.next70ContextAssignSeats
              = this.prev80ContextMakePath
              = this.next80ContextMakePath
              = this.prev90ContextCheckDone
              = this.next90ContextCheckDone
              = this.prev100ContextPrintResults
              = this.next100ContextPrintResults = null;
            }
        }

        public class EtCount : EntityTuple
        {
            private int countC;
            private bool cacheCountC;

            private EtCount prev10Count;
            private EtCount next10Count;


            public override Tuple GetNextTuple(int indexerId)
            {
                return this.next10Count;
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                return this.prev10Count;
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                this.next10Count = (EtCount)tuple;
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                this.prev10Count = (EtCount)tuple;
            }

            public int CountC
            {
                get
                {
                    switch (!this.cacheCountC)
                    {
                        case true:
                            SetCache("CountC");
                            break;
                    }

                    return this.countC;

                }

                set
                {
                    this.countC = value;
                    this.cacheCountC = true;
                    AddToCacheRemovalList("CountC");
                }
            }

            public override object Fact
            {
                get
                {
                    return base.Fact;
                }

                set
                {
                    base.Fact = value;

                    switch (IsINotifyPropertyChanged(value))
                    {
                        case true:
                            ((System.ComponentModel.INotifyPropertyChanged)value).PropertyChanged += this.BoundFactPropertyChanged;
                            break;
                    }

                    this.SetCache();  // Only want to do this if there is anything cacheable and not lazy eval
                }
            }

            protected override void SetCache()
            {
                this.CountC = Count.C;
                this.cacheCountC = true;
            }

            protected override void SetCache(string memberName)
            {
                switch (memberName)
                {
                    case "CountC":
                        this.CountC = Count.C;
                        this.cacheCountC = true;
                        break;
                }
            }

            public override void UpdateFact()
            {
                foreach (var memberName in this.cacheRemovalList)
                {
                    switch (memberName)
                    {
                        case "CountC":
                            Count.C = this.CountC;
                            break;
                    }
                }

                this.cacheRemovalList.Clear();
            }

            // TODO:   Not yet generating code for this
            public override void Clear()
            {
                base.Clear();

                this.countC = default(int);

                this.cacheCountC = false;

                this.prev10Count
              = this.next10Count = null;

            }
        }

        public class EtGuest : EntityTuple
        {
            private string guestName;
            private string guestSex;
            private string guestHobby;
            private bool cacheGuestName;
            private bool cacheGuestSex;
            private bool cacheGuestHobby;

            private EtGuest prev20Guest;
            private EtGuest next20Guest;
            private EtGuest prev21GuestName;
            private EtGuest next21GuestName;
            private EtGuest prev22GuestSex;
            private EtGuest next22GuestSex;
            private EtGuest prev23GuestHobby;
            private EtGuest next23GuestHobby;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next20Guest;
                    case 1:
                        return this.next21GuestName;
                    case 2:
                        return this.next22GuestSex;
                    case 3:
                        return this.next23GuestHobby;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev20Guest;
                    case 1:
                        return this.prev21GuestName;
                    case 2:
                        return this.prev22GuestSex;
                    case 3:
                        return this.prev23GuestHobby;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next20Guest = (EtGuest)tuple;
                        break;
                    case 1:
                        this.next21GuestName = (EtGuest)tuple;
                        break;
                    case 2:
                        this.next22GuestSex = (EtGuest)tuple;
                        break;
                    case 3:
                        this.next23GuestHobby = (EtGuest)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev20Guest = (EtGuest)tuple;
                        break;
                    case 1:
                        this.prev21GuestName = (EtGuest)tuple;
                        break;
                    case 2:
                        this.prev22GuestSex = (EtGuest)tuple;
                        break;
                    case 3:
                        this.prev23GuestHobby = (EtGuest)tuple;
                        break;
                }
            }

            public string GuestName
            {
                get
                {
                    switch (!this.cacheGuestName)
                    {
                        case true:
                            SetCache("Guest_Name");
                            break;
                    }

                    return this.guestName;

                }

                set
                {
                    this.guestName = value;
                    this.cacheGuestName = true;
                    AddToCacheRemovalList("Guest_Name");
                }
            }

            public string GuestSex
            {
                get
                {
                    switch (!this.cacheGuestSex)
                    {
                        case true:
                            SetCache("Guest_Sex");
                            break;
                    }

                    return this.guestSex;

                }

                set
                {
                    this.guestSex = value;
                    this.cacheGuestSex = true;
                    AddToCacheRemovalList("Guest_Sex");
                }
            }

            public string GuestHobby
            {
                get
                {
                    switch (!this.cacheGuestHobby)
                    {
                        case true:
                            SetCache("Guest_Hobby");
                            break;
                    }

                    return this.guestHobby;

                }

                set
                {
                    this.guestHobby = value;
                    this.cacheGuestHobby = true;
                    AddToCacheRemovalList("Guest_Hobby");
                }
            }

            public override object Fact
            {
                get
                {
                    return base.Fact;
                }

                set
                {
                    base.Fact = value;

                    switch (IsINotifyPropertyChanged(value))
                    {
                        case true:
                            ((System.ComponentModel.INotifyPropertyChanged)value).PropertyChanged += this.BoundFactPropertyChanged;
                            break;
                    }

                    this.SetCache();  // Only want to do this if there is anything cacheable and not lazy eval
                }
            }

            protected override void SetCache()
            {
                this.GuestName = ((Guest)this.Fact).Name;
                this.GuestSex = ((Guest)this.Fact).Sex;
                this.GuestHobby = ((Guest)this.Fact).Hobby;
                this.cacheGuestName = true;
                this.cacheGuestSex = true;
                this.cacheGuestHobby = true;
            }

            protected override void SetCache(string memberName)
            {
                switch (memberName)
                {
                    case "Guest_Name":
                        this.GuestName = ((Guest)this.Fact).Name;
                        this.cacheGuestName = true;
                        break;
                    case "Guest_Sex":
                        this.GuestSex = ((Guest)this.Fact).Sex;
                        this.cacheGuestSex = true;
                        break;
                    case "Guest_Hobby":
                        this.GuestHobby = ((Guest)this.Fact).Hobby;
                        this.cacheGuestHobby = true;
                        break;
                }
            }

            public override void UpdateFact()
            {
                foreach (var memberName in this.cacheRemovalList)
                {
                    switch (memberName)
                    {
                        case "Guest_Name":
                            ((Guest)this.Fact).Name = this.GuestName;
                            break;
                        case "Guest_Sex":
                            ((Guest)this.Fact).Sex = this.GuestSex;
                            break;
                        case "Guest_Hobby":
                            ((Guest)this.Fact).Hobby = this.GuestHobby;
                            break;
                    }
                }

                this.cacheRemovalList.Clear();
            }

            // TODO:   Not yet generating code for this
            public override void Clear()
            {
                base.Clear();

                this.guestName = default(string);
                this.guestSex = default(string);
                this.guestHobby = default(string);

                this.cacheGuestName
              = this.cacheGuestSex
              = this.cacheGuestHobby = false;

                this.prev20Guest
              = this.next20Guest
              = this.prev21GuestName
              = this.next21GuestName
              = this.prev22GuestSex
              = this.next22GuestSex
              = this.prev23GuestHobby
              = this.next23GuestHobby = null;
            }
        }

        public class EtLastSeat : EntityTuple
        {
            private int lastSeatSeat;
            private bool cacheLastSeatSeat;

            private EtLastSeat prev50LastSeat;
            private EtLastSeat next50LastSeat;
            private EtLastSeat prev51LastSeatSeat;
            private EtLastSeat next51LastSeatSeat;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next50LastSeat;
                    case 1:
                        return this.next51LastSeatSeat;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev50LastSeat;
                    case 1:
                        return this.prev51LastSeatSeat;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next50LastSeat = (EtLastSeat)tuple;
                        break;
                    case 1:
                        this.next51LastSeatSeat = (EtLastSeat)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev50LastSeat = (EtLastSeat)tuple;
                        break;
                    case 1:
                        this.prev51LastSeatSeat = (EtLastSeat)tuple;
                        break;
                }
            }

            public int LastSeatSeat
            {
                get
                {
                    switch (!this.cacheLastSeatSeat)
                    {
                        case true:
                            SetCache("LastSeat_Seat");
                            break;
                    }

                    return this.lastSeatSeat;

                }

                set
                {
                    this.lastSeatSeat = value;
                    this.cacheLastSeatSeat = true;
                    AddToCacheRemovalList("LastSeat_Seat");
                }
            }

            public override object Fact
            {
                get
                {
                    return base.Fact;
                }

                set
                {
                    base.Fact = value;

                    switch (IsINotifyPropertyChanged(value))
                    {
                        case true:
                            ((System.ComponentModel.INotifyPropertyChanged)value).PropertyChanged += this.BoundFactPropertyChanged;
                            break;
                    }

                    this.SetCache();  // Only want to do this if there is anything cacheable and not lazy eval
                }
            }

            protected override void SetCache()
            {
                this.LastSeatSeat = LastSeat.Seat;
                this.cacheLastSeatSeat = true;
            }

            protected override void SetCache(string memberName)
            {
                switch (memberName)
                {
                    case "LastSeat_Attribute1":
                        this.LastSeatSeat = LastSeat.Seat;
                        this.cacheLastSeatSeat = true;
                        break;
                }
            }

            public override void UpdateFact()
            {
                foreach (var memberName in this.cacheRemovalList)
                {
                    switch (memberName)
                    {
                        case "LastSeat_Seat":
                            LastSeat.Seat = this.LastSeatSeat;
                            break;
                    }
                }

                this.cacheRemovalList.Clear();
            }

            // TODO:   Not yet generating code for this
            public override void Clear()
            {
                base.Clear();

                this.lastSeatSeat = default(int);

                this.cacheLastSeatSeat = false;

                this.prev50LastSeat
              = this.next50LastSeat
              = this.prev51LastSeatSeat
              = this.next51LastSeatSeat = null;
            }
        }

        public class EtPath : EntityTuple
        {
            private int pathId;
            private string pathName;
            private bool cachePathId;
            private bool cachePathName;

            private EtPath prev40PathId;
            private EtPath next40PathId;
            private EtPath prev41PathName;
            private EtPath next41PathName;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next40PathId;
                    case 1:
                        return this.next41PathName;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev40PathId;
                    case 1:
                        return this.prev41PathName;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next40PathId = (EtPath)tuple;
                        break;
                    case 1:
                        this.next41PathName = (EtPath)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev40PathId = (EtPath)tuple;
                        break;
                    case 1:
                        this.prev41PathName = (EtPath)tuple;
                        break;
                }
            }

            public int PathId
            {
                get
                {
                    switch (!this.cachePathId)
                    {
                        case true:
                            SetCache("Path_Id");
                            break;
                    }

                    return this.pathId;
                }

                set
                {
                    this.pathId = value;
                    this.cachePathId = true;
                    AddToCacheRemovalList("Path_Id");
                }
            }

            public string PathName
            {
                get
                {
                    switch (!this.cachePathName)
                    {
                        case true:
                            SetCache("Path_Name");
                            break;
                    }

                    return this.pathName;
                }

                set
                {
                    this.pathName = value;
                    this.cachePathName = true;
                    AddToCacheRemovalList("Path_Name");
                }
            }

            public override object Fact
            {
                get
                {
                    return base.Fact;
                }

                set
                {
                    base.Fact = value;

                    switch (IsINotifyPropertyChanged(value))
                    {
                        case true:
                            ((System.ComponentModel.INotifyPropertyChanged)value).PropertyChanged += this.BoundFactPropertyChanged;
                            break;
                    }

                    this.SetCache();  // Only want to do this if there is anything cacheable and not lazy eval
                }
            }

            protected override void SetCache()
            {
                this.PathId = ((Path)this.Fact).Id;
                this.PathName = ((Path)this.Fact).Name;
                this.cachePathId = true;
                this.cachePathName = true;
            }

            protected override void SetCache(string memberName)
            {
                switch (memberName)
                {
                    case "Path_Id":
                        this.PathId = ((Path)this.Fact).Id;
                        this.cachePathId = true;
                        break;
                    case "Path_Name":
                        this.PathName = ((Path)this.Fact).Name;
                        this.cachePathName = true;
                        break;
                }
            }

            public override void UpdateFact()
            {
                foreach (var memberName in this.cacheRemovalList)
                {
                    switch (memberName)
                    {
                        case "Path_Id":
                            ((Path)this.Fact).Id = this.PathId;
                            break;
                        case "Path_Name":
                            ((Path)this.Fact).Name = this.PathName;
                            break;
                    }
                }

                this.cacheRemovalList.Clear();
            }

            // TODO:   Not yet generating code for this
            public override void Clear()
            {
                base.Clear();

                this.PathId = default(int);
                this.PathName = default(string);

                this.cachePathId
              = this.cachePathName = false;

                this.prev40PathId
              = this.next40PathId
              = this.prev41PathName
              = this.next41PathName = null;
            }
        }

        public class EtSeating : EntityTuple
        {
            private string seatingPathDone;
            private int seatingSeat2;
            private bool cacheSeatingPathDone;
            private bool cacheSeatingSeat2;

            private EtSeating prev110Seating;
            private EtSeating next110Seating;
            private EtSeating prev121SeatingYes;
            private EtSeating next121SeatingYes;
            private EtSeating prev132SeatingNo;
            private EtSeating next132SeatingNo;
            private EtSeating prev113SeatingSeat2;
            private EtSeating next113SeatingSeat2;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next110Seating;
                    case 1:
                        return this.next121SeatingYes;
                    case 2:
                        return this.next132SeatingNo;
                    case 3:
                        return this.next113SeatingSeat2;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev110Seating;
                    case 1:
                        return this.prev121SeatingYes;
                    case 2:
                        return this.prev132SeatingNo;
                    case 3:
                        return this.prev113SeatingSeat2;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next110Seating = (EtSeating)tuple;
                        break;
                    case 1:
                        this.next121SeatingYes = (EtSeating)tuple;
                        break;
                    case 2:
                        this.next132SeatingNo = (EtSeating)tuple;
                        break;
                    case 3:
                        this.next113SeatingSeat2 = (EtSeating)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev110Seating = (EtSeating)tuple;
                        break;
                    case 1:
                        this.prev121SeatingYes = (EtSeating)tuple;
                        break;
                    case 2:
                        this.prev132SeatingNo = (EtSeating)tuple;
                        break;
                    case 3:
                        this.prev113SeatingSeat2 = (EtSeating)tuple;
                        break;
                }
            }

            public string SeatingPathDone
            {
                get
                {
                    switch (!this.cacheSeatingPathDone)
                    {
                        case true:
                            SetCache("SeatingPathDone");
                            break;
                    }

                    return this.seatingPathDone;

                }

                set
                {
                    this.seatingPathDone = value;
                    this.cacheSeatingPathDone = true;
                    AddToCacheRemovalList("SeatingPathDone");
                }
            }

            public int SeatingSeat2
            {
                get
                {
                    switch (!this.cacheSeatingSeat2)
                    {
                        case true:
                            SetCache("Seating_Seat2");
                            break;
                    }

                    return this.seatingSeat2;

                }

                set
                {
                    this.seatingSeat2 = value;
                    this.cacheSeatingSeat2 = true;
                    AddToCacheRemovalList("Seating_Seat2");
                }
            }

            public override object Fact
            {
                get
                {
                    return base.Fact;
                }

                set
                {
                    base.Fact = value;

                    switch (IsINotifyPropertyChanged(value))
                    {
                        case true:
                            ((System.ComponentModel.INotifyPropertyChanged)value).PropertyChanged += this.BoundFactPropertyChanged;
                            break;
                    }

                    this.SetCache();  // Only want to do this if there is anything cacheable and not lazy eval
                }
            }

            protected override void SetCache()
            {
                this.SeatingPathDone = ((Seating)this.Fact).PathDone;
                this.SeatingSeat2 = ((Seating)this.Fact).Seat2;
                this.cacheSeatingPathDone = true;
                this.cacheSeatingSeat2 = true;
            }

            protected override void SetCache(string memberName)
            {
                switch (memberName)
                {
                    case "SeatingPathDone":
                        this.SeatingPathDone = ((Seating)this.Fact).PathDone;
                        this.cacheSeatingPathDone = true;
                        break;
                    case "Seating_Seat2":
                        this.SeatingSeat2 = ((Seating)this.Fact).Seat2;
                        this.cacheSeatingSeat2 = true;
                        break;
                }
            }

            public override void UpdateFact()
            {
                foreach (var memberName in this.cacheRemovalList)
                {
                    switch (memberName)
                    {
                        case "SeatingPathDone":
                            ((Seating)this.Fact).PathDone = this.SeatingPathDone;
                            break;
                        case "Seating_Seat2":
                            ((Seating)this.Fact).Seat2 = this.SeatingSeat2;
                            break;
                    }
                }

                this.cacheRemovalList.Clear();
            }

            // TODO:   Not yet generating code for this
            public override void Clear()
            {
                base.Clear();

                this.seatingPathDone = default(string);
                this.seatingSeat2 = default(int);

                this.cacheSeatingPathDone
              = this.cacheSeatingSeat2 = false;

                this.prev110Seating
              = this.next110Seating
              = this.prev121SeatingYes
              = this.next121SeatingYes
              = this.prev132SeatingNo
              = this.next132SeatingNo
              = this.prev113SeatingSeat2
              = this.next113SeatingSeat2 = null;
            }
        }

        public class JoinRoot1 : Tuple
        {
            // Cache the fact

            public string GuestName;
            protected int countC;

            private JoinRoot1 prev140J1;
            private JoinRoot1 next140J1;

            public override Tuple GetNextTuple(int indexerId)
            {
                return this.next140J1;
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                return this.prev140J1;
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                this.next140J1 = (JoinRoot1)tuple;
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                this.prev140J1 = (JoinRoot1)tuple;
            }

            public int CountC
            {
                get { return this.countC; }
                set { this.countC = value; }
            }

            public string ContextState { get; set; }

            public Context ContextFact { get; set; }

            public Guest GuestFact { get; set; }

            public Count CountFact { get; set; }

            public override void Clear()
            {
                base.Clear();

                this.ContextFact = default(Context);
                this.GuestFact = default(Guest);
                this.CountFact = default(Count);

                this.CountC = default(int);
                this.GuestName
              = this.ContextState = default(string);

                this.prev140J1
              = this.next140J1 = null;
            }
        }

        public class J1 : JoinRoot1
        {
        }

        public class AssignFirstSeat : JoinRoot1
        {
            public AssignFirstSeat()
            {
                ProductionName = "Assign First Seat";
                Salience = 0;
                Specificity = 1;
                Position = 1;
                ////Id = 0;
            }

            public new int CountC
            {
                get
                {
                    Count.C = this.countC;
                    return this.countC;
                }

                set
                {
                    this.countC = value;
                    Count.C = this.countC;
                }
            }

            public new string ContextState
            {
                get
                {
                    Context.State = base.ContextState;
                    return base.ContextState;
                }

                set
                {
                    base.ContextState = value;
                    Context.State = base.ContextState;
                }
            }

            public new Context ContextFact
            {
                get
                {
                    return base.ContextFact;
                }

                set
                {
                    base.ContextFact = value;

                    // Cache the data values
                    this.ContextState = Context.State;
                }
            }

            public new Guest GuestFact
            {
                get
                {
                    return base.GuestFact;
                }

                set
                {
                    base.GuestFact = value;

                    // Cache the data values
                    this.GuestName = base.GuestFact.Name;
                }
            }

            public new Count CountFact
            {
                get
                {
                    return base.CountFact;
                }

                set
                {
                    base.CountFact = value;

                    // Cache the data values
                    this.CountC = Count.C;
                }
            }

            public override ProductionEngineOps DoActions(ProductionEngineOps productionEngineOps)
            {
                productionEngineOps.Assertions.Add(new Seating(1, this.GuestName, this.GuestName, 1, this.CountC, 0, "yes"));
                productionEngineOps.Assertions.Add(new Path(this.CountC, this.GuestName, 1));
                this.CountC++;
                System.Diagnostics.Debug.Assert(this.CountFact != null);
                productionEngineOps.Modifications.Add(this.CountFact);
                Context.PrintResultAssignFirstSeat(this.GuestName, this.CountC);
                System.Diagnostics.Debug.WriteLine(string.Format("seat 1 {0} {0} 1 {1} 0 1", this.GuestName, this.CountC));
                this.ContextState = "assign_seats";
                productionEngineOps.Modifications.Add(this.ContextFact);
                return productionEngineOps;
            }

            public override void Clear()
            {
                base.Clear();

                this.AgendaNext
              = this.AgendaPrevious = null;
            }
        }

        public class JoinRoot2 : Tuple
        {
            // Cache the fact

            public int SeatingId;
            public string SeatingName2;
            public int SeatingSeat2;
            public string Guest1Sex;
            public string Guest1Hobby;
            public string Guest2Name;

            private JoinRoot2 prev170J5;
            private JoinRoot2 next170J5;
            private JoinRoot2 prev180J6;
            private JoinRoot2 next180J6;
            private JoinRoot2 prev150J3;
            private JoinRoot2 next150J3;
            private JoinRoot2 prev160J4;
            private JoinRoot2 next160J4;
            private JoinRoot2 prev161J4;
            private JoinRoot2 next161J4;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next170J5;
                    case 1:
                        return this.next180J6;
                    case 2:
                        return this.next150J3;
                    case 3:
                        return this.next160J4;
                    case 4:
                        return this.next161J4;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev170J5;
                    case 1:
                        return this.prev180J6;
                    case 2:
                        return this.prev150J3;
                    case 3:
                        return this.prev160J4;
                    case 4:
                        return this.prev161J4;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next170J5 = (JoinRoot2)tuple;
                        break;
                    case 1:
                        this.next180J6 = (JoinRoot2)tuple;
                        break;
                    case 2:
                        this.next150J3 = (JoinRoot2)tuple;
                        break;
                    case 3:
                        this.next160J4 = (JoinRoot2)tuple;
                        break;
                    case 4:
                        this.next161J4 = (JoinRoot2)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev170J5 = (JoinRoot2)tuple;
                        break;
                    case 1:
                        this.prev180J6 = (JoinRoot2)tuple;
                        break;
                    case 2:
                        this.prev150J3 = (JoinRoot2)tuple;
                        break;
                    case 3:
                        this.prev160J4 = (JoinRoot2)tuple;
                        break;
                    case 4:
                        this.prev161J4 = (JoinRoot2)tuple;
                        break;
                }
            }

            public int CountC { get; set; }

            public string ContextState { get; set; }

            public Context ContextFact { get; set; }

            public Seating SeatingFact { get; set; }

            public Guest Guest1Fact { get; set; }

            public Guest Guest2Fact { get; set; }

            public Count CountFact { get; set; }

            public override void Clear()
            {
                base.Clear();

                this.ContextFact = default(Context);
                this.SeatingFact = default(Seating);
                this.Guest1Fact
              = this.Guest2Fact = default(Guest);
                this.CountFact = null;

                this.SeatingId
              = this.SeatingSeat2 = default(int);

                this.SeatingName2
              = this.Guest1Sex
              = this.Guest1Hobby
              = this.Guest2Name = default(string);

                this.prev170J5
              = this.next170J5
              = this.prev180J6
              = this.next180J6
              = this.prev150J3
              = this.next150J3
              = this.prev160J4
              = this.next160J4
              = this.prev161J4
              = this.next161J4 = null;
            }
        }

        public class J3 : JoinRoot2
        {
            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }

                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingName2 = base.SeatingFact.Name2;
                }
            }
        }

        public class J4 : JoinRoot2
        {
            public new Guest Guest1Fact
            {
                get
                {
                    return base.Guest1Fact;
                }

                set
                {
                    base.Guest1Fact = value;

                    // Cache the data values
                    this.Guest1Sex = base.Guest1Fact.Sex;
                    this.Guest1Hobby = base.Guest1Fact.Hobby;
                }
            }
        }

        public class J5 : JoinRoot2
        {
        }

        public class J6 : JoinRoot2
        {
            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }

                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingId = base.SeatingFact.Id;
                }
            }

            public new Guest Guest1Fact
            {
                get
                {
                    return base.Guest1Fact;
                }

                set
                {
                    base.Guest1Fact = value;

                    // Cache the data values
                    this.Guest1Hobby = base.Guest1Fact.Hobby;
                }
            }

            public new Guest Guest2Fact
            {
                get
                {
                    return base.Guest2Fact;
                }

                set
                {
                    base.Guest2Fact = value;

                    // Cache the data values
                    this.Guest2Name = base.Guest2Fact.Name;
                }
            }
        }

        public class FindSeating : JoinRoot2
        {
            public FindSeating()
            {
                ProductionName = "Find Seating";
                Salience = 0;
                Specificity = 7;
                Position = 2;
                ////Id = 0;
            }

            public new int CountC
            {
                get
                {
                    Count.C = base.CountC;
                    return base.CountC;
                }

                set
                {
                    base.CountC = value;
                    Count.C = base.CountC;
                }
            }

            public new string ContextState
            {
                get
                {
                    Context.State = base.ContextState;
                    return base.ContextState;
                }

                set
                {
                    base.ContextState = value;
                    Context.State = base.ContextState;
                }
            }

            public new Context ContextFact
            {
                get
                {
                    return base.ContextFact;
                }

                set
                {
                    base.ContextFact = value;

                    // Cache the data values
                    this.ContextState = Context.State;
                }
            }

            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }

                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingId = base.SeatingFact.Id;
                    this.SeatingName2 = base.SeatingFact.Name2;
                    this.SeatingSeat2 = base.SeatingFact.Seat2;
                }
            }

            public new Guest Guest1Fact
            {
                get
                {
                    return base.Guest1Fact;
                }

                set
                {
                    base.Guest1Fact = value;

                    // Cache the data values
                    this.Guest1Hobby = base.Guest1Fact.Hobby;
                }
            }

            public new Guest Guest2Fact
            {
                get
                {
                    return base.Guest2Fact;
                }

                set
                {
                    base.Guest2Fact = value;

                    // Cache the data values
                    this.Guest2Name = base.Guest2Fact.Name;
                }
            }

            public new Count CountFact
            {
                get
                {
                    return base.CountFact;
                }

                set
                {
                    base.CountFact = value;

                    // Cache the data values
                    this.CountC = Count.C;
                }
            }

            public override ProductionEngineOps DoActions(ProductionEngineOps productionEngineOps)
            {
                productionEngineOps.Assertions.Add(new Seating(this.SeatingSeat2, this.SeatingName2, this.Guest2Name, this.SeatingSeat2 + 1, this.CountC, this.SeatingId, "no"));
                productionEngineOps.Assertions.Add(new Path(this.CountC, this.Guest2Name, this.SeatingSeat2 + 1));
                productionEngineOps.Assertions.Add(new Chosen(this.SeatingId, this.Guest2Name, this.Guest1Hobby));
                this.CountC++;
                productionEngineOps.Modifications.Add(this.CountFact);
                Context.PrintResultFindSeating(this.SeatingSeat2, this.SeatingName2, this.Guest2Name);
                System.Diagnostics.Debug.WriteLine(string.Format("seat {0} {1} {2}", this.SeatingSeat2, this.SeatingName2, this.Guest2Name));
                this.ContextState = "make_path";
                productionEngineOps.Modifications.Add(this.ContextFact);
                return productionEngineOps;
            }

            public override void Clear()
            {
                base.Clear();

                this.AgendaNext
              = this.AgendaPrevious = null;
            }
        }

        public class JoinRoot3 : Tuple
        {
            // Cache the fact

            public int SeatingId;
            public int SeatingPid;
            public string PathName;
            public int PathSeat;

            private JoinRoot3 prev200J8;
            private JoinRoot3 next200J8;
            private JoinRoot3 prev190J7;
            private JoinRoot3 next190J7;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next200J8;
                    case 1:
                        return this.next190J7;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev200J8;
                    case 1:
                        return this.prev190J7;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next200J8 = (JoinRoot3)tuple;
                        break;
                    case 1:
                        this.next190J7 = (JoinRoot3)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev200J8 = (JoinRoot3)tuple;
                        break;
                    case 1:
                        this.prev190J7 = (JoinRoot3)tuple;
                        break;
                }
            }

            public string SeatingPathDone { get; set; }

            public string ContextState { get; set; }

            public Context ContextFact { get; set; }

            public Seating SeatingFact { get; set; }

            public Path PathFact { get; set; }

            public override void Clear()
            {

                base.Clear();

                this.SeatingFact = default(Seating);
                this.ContextFact = default(Context);
                this.PathFact = default(Path);

                this.SeatingId
              = this.SeatingPid
              = this.PathSeat = default(int);
                this.SeatingPathDone
              = this.PathName = default(string);

                this.prev200J8
              = this.next200J8
              = this.prev190J7
              = this.next190J7 = null;
            }
        }

        public class J7 : JoinRoot3
        {
            ////////#if FULL_ASYMMETRIC_RETRACT
            ////////            public J7()
            ////////            {
            ////////                this.SubsumerEntries = new SubsumerEntry[4];
            ////////            }
            ////////#endif

            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }

                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingPid = base.SeatingFact.Pid;
                }
            }
        }

        public class J8 : JoinRoot3
        {
            //public J8()
            //{
            //    this.TupleSubsumersList = new TupleSubsumers[2]();
            //}

            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }

                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingId = base.SeatingFact.Id;
                }
            }

            public new Path PathFact
            {
                get
                {
                    return base.PathFact;
                }

                set
                {
                    base.PathFact = value;

                    // Cache the data values
                    this.PathName = base.PathFact.Name;
                }
            }
        }

        public class MakePath : JoinRoot3
        {
            public MakePath()
            {
                ProductionName = "Make Path";
                Salience = 1;
                Specificity = 4;
                Position = 3;
                ////Id = 0;
            }

            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }

                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingId = base.SeatingFact.Id;
                }
            }

            public new Path PathFact
            {
                get
                {
                    return base.PathFact;
                }

                set
                {
                    base.PathFact = value;

                    // Cache the data values
                    this.PathName = base.PathFact.Name;
                    this.PathSeat = base.PathFact.Seat;
                }
            }

            public override ProductionEngineOps DoActions(ProductionEngineOps productionEngineOps)
            {
                productionEngineOps.Assertions.Add(new Path(this.SeatingId, this.PathName, this.PathSeat));
                return productionEngineOps;
            }

            public override void Clear()
            {
                base.Clear();

                this.AgendaNext
              = this.AgendaPrevious = null;
            }
        }

        public class PathDone : JoinRoot3
        {
            public PathDone()
            {
                ProductionName = "Path Done";
                Salience = 0;
                Specificity = 2;
                Position = 4;
                ////Id = 0;
            }

            protected new string SeatingPathDone
            {
                get
                {
                    return base.SeatingPathDone;
                }

                set
                {
                    base.SeatingPathDone = value;
                    base.SeatingFact.PathDone = base.SeatingPathDone;
                }
            }

            protected new string ContextState
            {
                get
                {
                    return this.ContextState;
                }

                set
                {
                    base.ContextState = value;
                    Context.State = base.ContextState;
                }
            }

            public new Context ContextFact
            {
                get
                {
                    return base.ContextFact;
                }

                set
                {
                    base.ContextFact = value;
                    // Cache the data values
                    this.ContextState = Context.State;
                }
            }

            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }

                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingPathDone = base.SeatingFact.PathDone;
                }
            }

            public override ProductionEngineOps DoActions(ProductionEngineOps productionEngineOps)
            {
                this.SeatingPathDone = "yes";
                productionEngineOps.Modifications.Add(this.SeatingFact);
                ContextState = "check_done";
                productionEngineOps.Modifications.Add(this.ContextFact);
                return productionEngineOps;
            }

            public override void Clear()
            {
                base.Clear();

                this.AgendaNext
              = this.AgendaPrevious = null;
            }
        }

        public class JoinRoot4 : Tuple
        {
            // Cache the fact

            public int LastSeatSeat;

            private JoinRoot4 prev210J9;
            private JoinRoot4 next210J9;

            public override Tuple GetNextTuple(int indexerId)
            {
                return this.next210J9;
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                return this.prev210J9;
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                this.next210J9 = (JoinRoot4)tuple;
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                this.prev210J9 = (JoinRoot4)tuple;
            }

            public string ContextState { get; set; }

            public Context ContextFact { get; set; }

            public LastSeat LastSeatFact { get; set; }

            public Seating SeatingFact { get; set; }

            public override void Clear()
            {
                base.Clear();

                this.SeatingFact = default(Seating);
                this.LastSeatFact = default(LastSeat);
                this.ContextFact = default(Context);

                this.LastSeatSeat = default(int);
                this.ContextState = default(string);

                this.prev210J9
              = this.next210J9 = null;
            }
        }

        public class J9 : JoinRoot4
        {
            //public J9()
            //{
            //    this.TupleSubsumersList = new TupleSubsumers[2]();
            //}

            public new LastSeat LastSeatFact
            {
                get
                {
                    return base.LastSeatFact;
                }

                set
                {
                    base.LastSeatFact = value;

                    // Cache the data values
                    this.LastSeatSeat = LastSeat.Seat;
                }
            }
        }

        public class AreWeDone : JoinRoot4
        {
            public AreWeDone()
            {
                ProductionName = "Are We Done";
                Salience = 1;
                Specificity = 1;
                Position = 5;
                ////Id = 0;
            }

            public new string ContextState
            {
                get
                {
                    Context.State = base.ContextState;
                    return base.ContextState;
                }

                set
                {
                    base.ContextState = value;
                    Context.State = base.ContextState;
                }
            }

            public new Context ContextFact
            {
                get
                {
                    return base.ContextFact;
                }

                set
                {
                    base.ContextFact = value;

                    // Cache the data values
                    this.ContextState = Context.State;
                }
            }

            public override ProductionEngineOps DoActions(ProductionEngineOps productionEngineOps)
            {
                Context.PrintResultAreWeDone();
                System.Diagnostics.Debug.WriteLine("Yes, we are done!!");
                this.ContextState = "print_results";
                productionEngineOps.Modifications.Add(this.ContextFact);
                return productionEngineOps;
            }

            public override void Clear()
            {
                base.Clear();

                this.AgendaNext
              = this.AgendaPrevious = null;
            }
        }

        public class Continue : JoinRoot4
        {
            public Continue()
            {
                ProductionName = "Continue";
                Salience = 0;
                Specificity = 1;
                Position = 6;
                ////Id = 0;
            }

            public new string ContextState
            {
                get
                {
                    Context.State = base.ContextState;
                    return base.ContextState;
                }

                set
                {
                    base.ContextState = value;
                    Context.State = base.ContextState;
                }
            }

            public new Context ContextFact
            {
                get
                {
                    return base.ContextFact;
                }

                set
                {
                    base.ContextFact = value;

                    // Cache the data values
                    this.ContextState = Context.State;
                }
            }

            public override ProductionEngineOps DoActions(ProductionEngineOps productionEngineOps)
            {
                this.ContextState = "assign_seats";
                productionEngineOps.Modifications.Add(this.ContextFact);
                return productionEngineOps;
            }

            public override void Clear()
            {
                base.Clear();

                this.AgendaNext
              = this.AgendaPrevious = null;
            }
        }

        public class JoinRoot5 : Tuple
        {
            // Cache the fact

            public int SeatingId;
            public int SeatingSeat2;
            public string PathName;
            public int PathSeat;

            private JoinRoot5 prev220J11;
            private JoinRoot5 next220J11;
            private JoinRoot5 prev230J12;
            private JoinRoot5 next230J12;

            public override Tuple GetNextTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.next220J11;
                    case 1:
                        return this.next230J12;
                    default:
                        return null;
                }
            }

            public override Tuple GetPreviousTuple(int indexerId)
            {
                switch (indexerId)
                {
                    case 0:
                        return this.prev220J11;
                    case 1:
                        return this.prev230J12;
                    default:
                        return null;
                }
            }

            public override void SetNextTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.next220J11 = (JoinRoot5)tuple;
                        break;
                    case 1:
                        this.next230J12 = (JoinRoot5)tuple;
                        break;
                }
            }

            public override void SetPreviousTuple(int indexerId, Tuple tuple)
            {
                switch (indexerId)
                {
                    case 0:
                        this.prev220J11 = (JoinRoot5)tuple;
                        break;
                    case 1:
                        this.prev230J12 = (JoinRoot5)tuple;
                        break;
                }
            }

            public Context ContextFact { get; set; }

            public Seating SeatingFact { get; set; }

            public LastSeat LastSeatFact { get; set; }

            public Path PathFact { get; set; }

            public override void Clear()
            {
                base.Clear();

                this.SeatingFact = default(Seating);
                this.ContextFact = default(Context);
                this.LastSeatFact = default(LastSeat);
                this.PathFact = default(Path);

                this.SeatingId
              = this.SeatingSeat2
              = this.PathSeat = default(int);
                this.PathName = default(string);

                this.prev220J11
              = this.next220J11
              = this.prev230J12
              = this.next230J12 = null;
            }
        }

        public class J11 : JoinRoot5
        {
            //public J11()
            //{
            //    this.TupleSubsumersList = new TupleSubsumers[2]();
            //}

            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }
                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingSeat2 = base.SeatingFact.Seat2;
                }
            }
        }

        public class J12 : JoinRoot5
        {
            //public J12()
            //{
            //    this.TupleSubsumersList = new TupleSubsumers[2]();
            //}

            public new Seating SeatingFact
            {
                get
                {
                    return base.SeatingFact;
                }
                set
                {
                    base.SeatingFact = value;

                    // Cache the data values
                    this.SeatingId = base.SeatingFact.Id;
                }
            }
        }

        public class PrintResults : JoinRoot5
        {
            public PrintResults()
            {
                ProductionName = "Print Results";
                Salience = 1;
                Specificity = 0;
                Position = 7;
                ////Id = 0;
            }

            public new Path PathFact
            {
                get
                {
                    return base.PathFact;
                }
                set
                {
                    base.PathFact = value;

                    // Cache the data values
                    this.PathName = base.PathFact.Name;
                    this.PathSeat = base.PathFact.Seat;
                }
            }

            public override ProductionEngineOps DoActions(ProductionEngineOps productionEngineOps)
            {
                productionEngineOps.Retractions.Add(base.PathFact);
                Context.PrintResults(this.PathName, this.PathSeat);
                System.Diagnostics.Debug.WriteLine(string.Format("{0} {1}", this.PathName, this.PathSeat));
                return productionEngineOps;
            }

            public override void Clear()
            {
                base.Clear();

                this.AgendaNext
              = this.AgendaPrevious = null;
            }
        }

        public class AllDone : JoinRoot5
        {
            public AllDone()
            {
                ProductionName = "All Done";
                Salience = 0;
                Specificity = 1;
                Position = 8;
                ////Id = 0;
            }

            public override ProductionEngineOps DoActions(ProductionEngineOps productionEngineOps)
            {
                // TODO:   mplement HALT and CLEAR
                //halt and clear all rule firings
                return productionEngineOps;
            }

            public override void Clear()
            {
                base.Clear();

                this.AgendaNext
              = this.AgendaPrevious = null;
            }

        }

        public static class Evaluators
        {
            public static IComparable EvaluatorPathId(EtPath tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Path.Id                ");
#endif
                return tuple.PathId;
            }

            public static IComparable EvaluatorPathName(EtPath tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Path.Name              ");
#endif
                return tuple.PathName;
            }

            public static IComparable EvaluatorChosenId(EtChosen tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Chosen.Id              ");
#endif
                return tuple.ChosenId;
            }

            public static IComparable EvaluatorChosenName(EtChosen tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Chosen.Name            ");
#endif
                return tuple.ChosenName;
            }

            public static IComparable EvaluatorChosenHobby(EtChosen tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Chosen.Hobby           ");
#endif
                return tuple.ChosenHobby;
            }

            public static IComparable EvaluatorGuestName(EtGuest tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Guest.Name             ");
#endif
                return tuple.GuestName;
            }

            public static IComparable EvaluatorGuestHobby(EtGuest tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Guest.Hobby:           ");
#endif
                return tuple.GuestHobby;
            }

            public static IComparable EvaluatorGuestSex(EtGuest tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Guest.Sex, Guest.Hobby:");
#endif
                return tuple.GuestSex;
            }

            public static IComparable EvaluatorSeatingSeat2(EtSeating tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         Seating.Seat2:         ");
#endif
                return tuple.SeatingSeat2;
            }

            public static IComparable EvaluatorLastSeatSeat(EtLastSeat tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("-         LastSeat.Seat:         ");
#endif
                return tuple.LastSeatSeat;
            }

            public static IComparable EvaluatorJSeq2J3SeatingName2(J3 tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("2   J3    Seating.Name2:         ");
#endif
                return tuple.SeatingName2;
            }

            public static IComparable EvaluatorJSeq2J4GuestSex(J4 tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("2   J4    Guest.Sex: ");
#endif
                return tuple.Guest1Sex;
            }

            public static IComparable EvaluatorJSeq2J4GuestHobby(J4 tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("2   J4    Guest.Hobby: ");
#endif
                return tuple.Guest1Hobby;
            }

            //////////            public static IComparable EvaluatorJSeq2J6SeatingId(J6 tuple)
            //////////            {
            //////////#if EVAL_COUNTS
            //////////                MannersExecutor.IncrementEvalCount("2   J6    Seating.Id:            ");
            //////////#endif
            //////////                return tuple.Seating_Id;
            //////////            }

            public static IComparable EvaluatorJSeq3J7SeatingPid(J7 tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("3   J7    Seating.Pid:           ");
#endif
                return tuple.SeatingPid;
            }

            public static IComparable EvaluatorJSeq4J9LastSeatingSeat(J9 tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("4   J9    LastSeating.Seat:      ");
#endif
                return tuple.LastSeatSeat;
            }

            public static IComparable EvaluatorJSeq5J11SeatingSeat2(J11 tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("5   J11   Seating.Seat2:         ");
#endif
                return tuple.SeatingSeat2;
            }

            public static IComparable EvaluatorJSeq5J12SeatingId(J12 tuple)
            {
#if EVAL_COUNTS
                MannersExecutor.IncrementEvalCount("5   J12   Seating.Id:            ");
#endif
                return tuple.SeatingId;
            }
        }

        public class PathIdName : IComparable<PathIdName>, ITupleRelationIndex
        {
            public PathIdName(int id, string name)
            {
                this.Id = id;
                this.Name = name;
            }

            public int Id { get; set; }

            public string Name { get; set; }

            #region IComparable<PathIdName> Members

            public int CompareTo(PathIdName other)
            {
                var idComp = this.Id.CompareTo(other.Id);
                var nameComp = this.Name.CompareTo(other.Name);

                switch (idComp > 1)
                {
                    case true:
                        idComp = 1;
                        break;
                }

                switch (idComp < -1)
                {
                    case true:
                        idComp = -1;
                        break;
                }

                switch (nameComp > 1)
                {
                    case true:
                        nameComp = 1;
                        break;
                }

                switch (nameComp < -1)
                {
                    case true:
                        nameComp = -1;
                        break;
                }

                return ((2 * idComp) + nameComp);
            }

            #endregion

            #region IComparable Members

            public int CompareTo(object obj)
            {
                return CompareTo((PathIdName)obj);
            }

            #endregion

            #region ITupleRelationIndex Members

            /// <summary>
            /// Filters A tuple list.  Compares the tuple list to a key-value pair from
            /// a tuple view.
            /// </summary>
            /// <typeparam name="T">The tuple type that is indexed.</typeparam>
            /// <param name="tupleLinkedListKey">A tuple linked list.</param>
            /// <param name="tupleViewEntry">A key-value pair entry from a tuple view.</param>
            /// <returns>Indicates if the tuple list matches the key-value pair.</returns>
            public bool Filter<T>(TupleLinkedList tupleLinkedListKey, KeyValuePair<T, TupleLinkedList> tupleViewEntry)
            {
                var key = tupleViewEntry.Key as PathIdName;

                return (/*(hsKey == tupleViewEntry.Value)
                      && */
                           this.Id == key.Id
                      && this.Name == key.Name);
            }

            #endregion
        }

        public class ChosenIdNameHobby : IComparable<ChosenIdNameHobby>, ITupleRelationIndex
        {
            public ChosenIdNameHobby(int id, string name, string hobby)
            {
                this.Id = id;
                this.Name = name;
                this.Hobby = hobby;
            }

            public int Id { get; set; }

            public string Name { get; set; }

            public string Hobby { get; set; }

            #region IComparable<ChosenIdNameHobby> Members

            public int CompareTo(ChosenIdNameHobby other)
            {
                var idComp = this.Id.CompareTo(other.Id);
                var nameComp = this.Name.CompareTo(other.Name);
                var hobbyComp = this.Hobby.CompareTo(other.Hobby);

                switch (idComp > 1)
                {
                    case true:
                        idComp = 1;
                        break;
                }

                switch (idComp < -1)
                {
                    case true:
                        idComp = -1;
                        break;
                }

                switch (nameComp > 1)
                {
                    case true:
                        nameComp = 1;
                        break;
                }

                switch (nameComp < -1)
                {
                    case true:
                        nameComp = -1;
                        break;
                }

                switch (hobbyComp > 1)
                {
                    case true:
                        hobbyComp = 1;
                        break;
                }

                switch (hobbyComp < -1)
                {
                    case true:
                        hobbyComp = -1;
                        break;
                }

                return ((3 * idComp) + (2 * nameComp) + hobbyComp);
            }

            #endregion

            #region IComparable Members

            public int CompareTo(object obj)
            {
                return CompareTo((ChosenIdNameHobby)obj);
            }

            #endregion

            #region ITupleRelationIndex Members

            /// <summary>
            /// Filters A tuple list.  Compares the tuple list to a key-value pair from
            /// a tuple view.
            /// </summary>
            /// <typeparam name="T">The tuple type that is indexed.</typeparam>
            /// <param name="tupleLinkedListKey">A tuple linked list.</param>
            /// <param name="tupleViewEntry">A key-value pair entry from a tuple view.</param>
            /// <returns>Indicates if the tuple list matches the key-value pair.</returns>
            public bool Filter<T>(TupleLinkedList tupleLinkedListKey, KeyValuePair<T, TupleLinkedList> tupleViewEntry)
            {
                var key = tupleViewEntry.Key as ChosenIdNameHobby;

                return (/*(hsKey == tupleViewEntry.Value)
                      && */
                           this.Id == key.Id
                      && this.Name == key.Name
                      && this.Hobby == key.Hobby);
            }

            #endregion
        }

        /// <summary>
        /// 
        /// </summary>
        private struct SelectionTargets
        {
            public readonly MonadicFunction MonadicFunction;
            public readonly ITupleRelation TupleRelation;

            public SelectionTargets(params MonadicFunction[] monadicFunctions)
            {
                this.MonadicFunction = null;
                this.TupleRelation = null;

                foreach (var bf in monadicFunctions)
                {
                    switch (this.MonadicFunction == null)
                    {
                        case true:
                            this.MonadicFunction = bf;
                            break;
                        default:
                            this.MonadicFunction += bf;
                            break;
                    }
                }
            }

            public SelectionTargets(ITupleRelation tr, params MonadicFunction[] monadicFunctions)
                : this(monadicFunctions)
            {
                this.TupleRelation = tr;
            }
        }
    }
}
